how does POST happen from /users and not /users/new - ruby-on-rails

i went through the default routes created by
resources :photos
over here : http://guides.rubyonrails.org/routing.html#crud-verbs-and-actions
im confused about:
POST /photos create create a new photo
when creating a new photo, isnt the POST happening from the /photos/new action?

/photos/new action returns the form to create a new photo.
After you fill the required information and clicked create then
/photos/create is called.

Just quoting Mischa:
"There is no redirect and /photos/create is never called. When you submit your form on /photos/new a POST request to /photos is done. Then Rails' router makes sure the create action in your controller is executed."
that was the right answer.

Related

Modify routes in rails

I'm a new user of rails so it's complicated to understand how the routes.rb works! So I try to modify a route, I got a path that look like this:
user/:id/edit but i want that the id not appear in the path.
I try to use this method :
get '/users/:id/edit', to: 'users#edit', as: 'users/edit'
but it changes nothing. In my routes.rb i got :
resources :users, only: [:create, :new, :show, :edit]
Someone know how to do this? I already take a look at this guide
If you already take a look at guides, do you read about singular resources?
Sometimes, you have a resource that clients always look up without
referencing an ID. For example, you would like /profile to always show
the profile of the currently logged in user. In this case, you can use
a singular resource to map /profile (rather than /profile/:id) to the
show action:
resource :geocoder
creates six different routes in your application, all mapping to the Geocoders controller:
GET /geocoder/new geocoders#new return an HTML form for creating the geocoder
POST /geocoder geocoders#create create the new geocoder
GET /geocoder geocoders#show display the one and only geocoder resource
GET /geocoder/edit geocoders#edit return an HTML form for editing the geocoder
PATCH/PUT /geocoder geocoders#update update the one and only geocoder resource
DELETE /geocoder geocoders#destroy delete the geocoder resource
If you have taken,
resources :users
Now change this route as follows,
get '/users/edit', to: 'users#edit', as: 'users_edit'
Now in your view file where you have edit link, change the link to,
<%= link_to 'Edit', users_edit_path(:id => user.id) %>
Now this links to the edit action of users controller with an id parameter.
Now, in the users controller file,
class UsersController < ApplicationController
def edit
// params[:id] will be the ID that you sent through the view file.
#user = User.find(params[:id])
end
end
Thats it, you are done with your custom route, now the route will be users/edit instead of users/:id/edit

RoR getting things to goto the right places

I have a few questions maybe if I can just tie them up all into one quick go here this could be a good reference for later.
I would like to render a partial [comments/new] in [posts/show]. Now being on our current page/show of posts#show we would be using the posts_controller.rb our model will be the one[s] we would like to call on at any point. -- I need to render [comments/new] in the [posts/show] with the comments_controller.rb enabled for that piece.
second the rake routes shows you a list of routes that are created for you.
post_comments GET /posts/:post_id/comments(.:format) comments#index
POST /posts/:post_id/comments(.:format) comments#create
new_post_comment GET /posts/:post_id/comments/new(.:format) comments#new
edit_post_comment GET /posts/:post_id/comments/:id/edit(.:format) comments#edit
post_comment GET /posts/:post_id/comments/:id(.:format) comments#show
PATCH /posts/:post_id/comments/:id(.:format) comments#update
PUT /posts/:post_id/comments/:id(.:format) comments#update
DELETE /posts/:post_id/comments/:id(.:format) comments#destroy
not sure what everything on this list is or how it works need some help on that one.
class and subclasses? can you have sub-sub-classes and how does linking a class and a subclass work inside of a simple app.
Views are not strictly tied to your controller. Rails is automagically set so that in the new action of the comments controller, it will try to render the views/comments/new view as long as there is no view specified.
You want to call an action from another action. You should not do that. You can call controller method that are not action from an action, but never an actual action.
The shortest answer would be, build an empty comment in the post show actioncontroller (as you probably do).
def show
#post = Post.find params[:id]
#comment= Comment.build
end
and in the view do :
<%=render "comments/form" %>
EDIT: corrected a typo, here it is rendering what we call a partial. A partial file always start with the _ character, but when you call it in the view, you do not put the _ in the path.
But maybe, a more important question is "do you need a new action in comments". Obviously your comments are always used in posts and you never have a use case asking for a comment created ex nihilo. In a case of a basic blog, i would only have a create and update action in my comments controller that would end with a redirect to post_show_path or :back
Nested resource are not really the best answer to your problem, it would be more fitted for something like a photo gallery where you have pages displaying a single photo :
galleries/:id_gallery/photo/:id
Using nested routes in a post/comment context, that would mean that you want to have a dedicated view to create a comment, and a view for each comment. You do not really need that.
:url => { :action => "create", :controller => "posts" }
anytime you can specify a :url I can use this format to call a specific controller and action no matter were I am playing in the views. I can render a partial with this :url in the pages#index then rails know hey don't use the pages controller use the posts controller.

Resource route in ruby and rails

I have
resources :blog
declared in my routes.rb file but when I try to access blog_path in a controller or a html.erb file, I get the following error:
No route matches {:controller=>"blog", :action=>"show"} missing required keys: [:id]
I have created a controller called BlogController and defined the method show with a show.html.erb file in the views directory. If I define:
match '/blog', to: 'blog#show', via: 'get' instead, then blog_path works fine.
My understanding is resources: blog is just syntactic sugar for match '/blog', to: 'blog#show', via: 'get' and a bunch of other routes. Please help.
blog_path is for generating path to a blog, so you need id or a blog object, this helper generates path like /blogs/12 to blogs#show, and blogs#show is for showing an object. blogs_path generates /blogs to blogs#index (like to all blogs).
Look at 2 Resource Routing: the Rails Default
resources :photos
GET /photos index display a list of all photos
GET /photos/new new return an HTML form for creating a new photo
POST /photos create create a new photo
GET /photos/:id show display a specific photo
GET /photos/:id/edit edit return an HTML form for editing a photo
PATCH/PUT /photos/:id update update a specific photo
DELETE /photos/:id destroy delete a specific photo
You have used resources :blog without s. It generates
blog_index GET /blog(.:format) blog#index
POST /blog(.:format) blog#create
new_blog GET /blog/new(.:format) blog#new
edit_blog GET /blog/:id/edit(.:format) blog#edit
blog GET /blog/:id(.:format) blog#show
PUT /blog/:id(.:format) blog#update
DELETE /blog/:id(.:format) blog#destroy
Make resource plural like this
resource :blogs
And make controller name blogs_controller.rb and its class name BlogsController
This is rails standard
I'm recently starting to use Rails, but I noticed that when Rails generates a controller for me, it names it with an underscore between the name and the word controller.
Something like blog_controller.rb. A few days ago I replaced one with other without the underscore and get a similar error, not sure why.

Dynamic path helpers rails

What are the paths that is automatically added by Rails? Let say you have a Question resource you automatically get questions_path, question_path etc. Where do I see what they resolve to and what I get?
This section might be helpful http://guides.rubyonrails.org/routing.html#specifying-a-controller-to-use
Verb Path Action Helper
GET /photos index photos_path
GET /photos/new new new_photo_path
POST /photos create photos_path
GET /photos/:id show photo_path(:id)
GET /photos/:id/edit edit edit_photo_path(:id)
PUT /photos/:id update photo_path(:id)
DELETE /photos/:id destroy photo_path(:id)
If you want to create a helper for show action you can write
photo_path(#photo.id)
where #photo is your model object. Or you can pass #photo directly if it responds to id method.
photo_path(#photo)
edit_photo_path(#photo)
You can also load rails console (in terminal) and test routes using app like so app.photo_path(1) (it will show you the route for the photo with id equals 1)
Just use:
rake routes
This will list all routes defined. The first column is relevant for you path helpers.
If you have the following in your routes file:
resources :questions
Then Rails provides the following restful routes for you:
GET /questions index list of questions
GET /questions/new new show new question form
POST /questions create create a new question
GET /questions/:id show show a specific question
GET /questions/:id/edit edit show form to edit question
PUT /questions/:id update update a specific question
DELETE /questions/:id destroy delete a specific question
You can also run rake:routes to see what is being generated.

custom action in rails 3

I'm trying to make a simple link that will toggle my "status" attribute in my model from "pending" to "active". For example, when I first create a user, I set the status to "pending". Then when I show the list of users, I add a button that should change that user's status to "active". I tried this via a custom action (is this a good approach?) but I'm having trouble with the auto-generated named route.
in my user index.html.haml:
button_to "Manually Activate", activate_user_path
in routes.rb:
resources :users do
get :activate, :on => :member
in users_controller.rb:
def activate
#user = User.find(params[:id])
#user.update_attribute(:status, 'Active')
redirect_to #user
end
this seems to work when I go to say, /users/1/activate, as the status will update. However, the /users page doesn't show and gives me error:
ActionController::RoutingError in Users#index
No route matches {:action=>"activate", :controller=>"users"}
ie, it is having a problem with the activate_user_path I specified in my view. (However if I use another named-routes-style path that I haven't specified in my routes.rb to test it out, I get
NameError in Users#index
undefined local variable or method `blahblah_user_url' for #<#<Class:0x00000102bd5d50>:0x00000102bb9588>
so it seems that it knows it's in the routes.rb but something else is wrong? I'm really new to rails and would appreciate the help!
thanks!
Your link should look like this:
button_to "Manually Activate", activate_user_path(#user)
You need to add what user you want to activate.
A number of problems, I can see.
Firstly you should NOT update the database using a GET request.
Secondly button_to will provide you with an inplace form which when clicked will POST to your app.
Thirdly, the way you have your routes setup, you need to provide the user in the path (you've tested it by forming the url in the browser already).
run
rake routes
on the command prompt to see how your routes look and the name you can use to generate those routes.
I suspect you need to use
button_to "Manually Activate", activate_user_path(user)
(user or #user or whatever is the user object). In your button_to call and change the "get" to "post" in the routes file.
resources :users do
member do
post :activate
end
end

Resources