Collection Routes with post - ruby-on-rails

To add a route to the collection photo I write :
resources :photos do
collection do
post 'myaction'
end
end
and this generates a path /photos/myaction. However, in case of the create action, Rails generates a path /photos not /photos/create. How can I configure my route.rb so that I could use photos_path instead of myaction_photos_path (just like the create action)?

Related

Referring to a nested resourse

I have a nested resource:
resources :res1 do
resources :res2
end
And I have a custom action in res2:
def my_action
end
which doesn't appear in the list of the pre-generated paths (there is no res1_res2_my_action_url url). I want to refer to my_action using controller and action notation but the following doesn't work:
url_for(controller: [:res1, :res2], action: :my_action)
Why is that?
The resources directive in your routes file will only create default routes for your controller.
#index
#new
#create
#show
#edit
#update
#destroy
If you want to add custom routes, you'll have to declare them like so:
resources :res1 do
resources :res2 do
get :my_action
end
end
you can hard code a specific route that points to action and controller:
get '/pathname', to: 'controller_name#my_action'
Try running rake routes and see what o/p you get,a try to apply in your view
get 'my_action' => "res2#my_action"
and then write
:url => my_action_path

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.

Trying to create a method in rails controller

I'm still trying to get the hang of rails and i'm trying to create a simple app with a form where i can enter the data and then submit it and it will be stored in the db. I got this very simple by starting a new project and then running:
$ rails generate scaffold RSVP firstName:string lastName:string
Now i want to redirect to a thank you page after adding a new record via the form.
I've manually added the method below to my rsvps_controller.rb file:
# GET /rsvps/thank_you
def thank_you
respond_to do |format|
format.html # thank_you.html.erb
format.json { render json: #rsvps }
end
end
This line is in my routes file:
resources :rsvps
My question is, when i run rake routes, i don't see a route for my thank_you method. Shouldn't my :rsvps resource pick up my thank_you route and how does the routes know which controller method are which http calls(get, post, put, etc)?
In order to get a route that will hit that action in your controller you should have in your routes.rb file something like:
resources :rsvps do
member { get :thank_you }
end
or
resources :rsvps do
collection { get :thank_you }
end
it depends for if you want to access the resource you've just created or not.
You can take a look # http://guides.rubyonrails.org/routing.html it should help you understating the routing mechanism better.
Adding on to what wlad said, the resources :rsvps things in your routes.rb file creates a set of default routes that are going to be needed by most models. Things like index, new, create, or show. The reason your thank_you action isn't showing up in rake routes is because thank_you isn't one of the actions that were so common that they needed to be included out of the box without extra code.
If you are going to need to load a rsvp model on the thank you page to display any data in that model then you will need to use a member route. The :id in the route will be there because this is a resources member route and has to be associated with a particular resource. There has to be something in the url to know what to load.
resources :rsvps do
member { get :thank_you } #GET /rsvps/:id/thank_you(.:format)
end
If you just want a generic route that points to that controller action then you can use something like this:
match "/rsvps/thank_you" => "rsvps#thank_you", as: "rsvp_thank_you"
You can add more actions to any controller but rails will not treat this functions as actions unless you specify them in routes file. It will be treated as just another function in controller class created by user.
so if you want to add the thank_you function as action you need to add this to routes file.
There are multiple ways of doing so as others have explained in their answers.
adding-more-restful-actions
Using member and collection inside resources.
Use member when you want the function to be used only with the some model object.
eg: preview for photo id 1
GET /photos/:id/preview
In our example you member if you want such route and functionality.
GET /rsvps/:id/thank_you
Note :id in params is needed when you specify it as a member action.
resources :rsvps do
member do
get :thank_you #GET /rsvps/:id/thank_you(.:format)
end
end
Use collection if you want to call the action directly like
GET /rsvps/thank_you(.:format)
in resources
resources :rsvps do
collection do
get :thank_you #GET /rsvps/thank_you(.:format)
end
end
You need to specify the type of action (GET|POST) while adding it to routes.
In our example thank_you has been specified as a GET action. You can choose either.
You can create you own preety_urls or non restful routes using match.
(This will also require to have the action defined in resources block).
check out more on match here http://guides.rubyonrails.org/routing.html#non-resourceful-routes
I suggest you to go through this awesome documentation created by the rails team.(once more ;) ) http://guides.rubyonrails.org/routing.html
Cheers.
As you have said you just want to show a thank you page for each rsvp so a member route should be used. like this
resources :rsvps do
member get :thank_you
end
You should use collection of thank_you when you want to show all or some specific collection of thank_you.
when you include this and run rake routes again you will see the new http action there.

What's the use of 'get controller/action' in routes.rb in rails 3.1?

When generating a controller, rails automatically put 'get controller/action' at top of routes.rb file for each of the resourceful action (such as index, new, create, edit. etc.). What's purpose of this 'get'? Since there is a 'resources' for the same model in routes.rb, can we get rid of this 'get'? Is the 'get' needed for 'put' custom action in routes.rb?
Thanks so much.
You can safely remove that route.
The proper layout for basic resource routing in Rails 3.1 follows this format:
resources :users do # Provides GET /users, /users/new, /users/:id, /users/:id/edit, POST /users, PUT /users/:id, DELETE /users/:id
# Additional routes which return collections (not CRUD)
collection do
get :search # /users/search
end
# Additional routes which return single models (not CRUD)
member do
put :add_friend # /users/:id/add_friend
end
end
You can read the full Rails routing guide here: http://guides.rubyonrails.org/routing.html

Add action to scaffold generated controller

I have created model, view and controller:
$ rails generate scaffold Post name:string title:string content:text
Then I have added the method on Post controller:
def fill_default_data
Post.fill_default_data
end
But when I have open http://localhost:3000/posts/fill_default_data in browser I get the error:
ActiveRecord::RecordNotFound in
PostsController#show
Couldn't find Post with
ID=fill_default_data
It looks like Rails don't see fill_default_data action and use show method. How can I add new method to scaffold generated controller?
You should add the relevant route to your config/routes.rb file. If you currently have:
resources :posts
You should change that to:
resources :posts do
collection do
get :fill_default_data
end
end
That will generate a route that you can access through /posts/fill_default_data. Now your app is actually accessing the show action and filling in "fill_default_data" as the ID.
Or if you want to add the method to a member rather than the collection, use the following:
resources :posts do
member do
get :fill_default_data, :as => 'fill_out_data'
end
end
This using member if preferred if you are performing the action on a single post rather than on a collection of posts. Also, the :as option generates named route helpers (stuff like *_path or *_url) in case you want them.

Resources