Rails: Nested Controller Custom Actions

I want to customize the actions of nested controllers, but I cannot figure out the routing.

I keep getting the following error:

No route matches [GET] "/assets" 

routes.rb

 resources :companies do resources :requests do match :accept end end 

index.html.rb

 <% @requests.each do |request| %> <ul class="users"> <li> <%= full_name(request.profile) %> <%= request.status %> <%= link_to "Accept", :controller => "requests", :action => "accept", :id => request.id %> </li> </ul> <% end %> 
+4
source share
2 answers

There are several problems: routing to an accept action and creating a URL for a nested resource.

Defining custom actions

Using this syntax, you can add custom actions to RESTful resources:

 resources :requests do get 'accept', :on => :member end 

This will give you a route that looks like this:

 requests/:id/accept 

And you can create paths in your views using:

 accept_request_path(a_request) 

The :on => :member indicates that you are routing a new action for each individual request, rather than collecting all the requests. If you used :on => :collection , the route would be requests/accept

Investment Resources

When you insert resources:

 resources :companies do resources :requests do get 'accept', :on => :member end end 

You get routes that look like this: note that since requests are nested within companies, the route includes both company_id and id :

 companies/:company_id/requests/:id/accept 

And helpers like this:

 accept_company_request_path(a_company, a_request) 

You could make this long arm, as you are trying to do now, with something like:

 <%= link_to "Accept", :controller => "requests", :action => "accept", :id => request.id, :company_id => request.company.id %> 

But it's easier to use helpers:

 <%= link_to "Accept", accept_company_request_path(request.company, request) %> 

Matching Verbs

Accept sounds in the same way as something that somehow updates your database, and if in this case you should consider a PUT request, not a GET request.

The HTTP / 1.1 specification suggests that the GET and HEAD methods SHOULD NOT have the value of taking an action other than retrieval ( RFC2616, section 9 ), which has the real meaning that non-human web clients are search engine indexes, extensions browser, etc. - can follow links (which make GET requests), but are not allowed to submit forms that make other types of requests.

If you switch to using the PUT request, the button_to helper will be useful to you . As in the case of link_to , you can pass to the controller, action, method and all the parameters necessary for the route to button_to :

 <%= button_to 'Accept', {:controller => :requests, :action => :accept, :company_id => request.company, :id => request}, :method => :put %> 

Or you can use helpers to create a path that is much simpler:

 <%= button_to 'Accept', accept_company_request_path(request.company, request), :method => :put %> 

Additional documentation

+23
source

in the route file:

 match 'request/accept/:id' => 'requests#accept', :as => :accept 

and in sight

 link_to "Accept", accept_path(request) 
+2
source

All Articles