Polymorphic routes pointed to same controller and action - ruby-on-rails

This is a polymorphic association!
resources :professors, :labs do
member do
resources :teaching_assistants
end
end
I want to have index for professors teaching assistants, labs teaching assistants and teaching assistants like so:
/professors/id/teaching_assistants
/labs/id/teaching_assistants
/teaching_assistants
All these routes are pointing to
teaching_assistants#index. Do i have to explicitly point the nested routes to an action in in the professors and labs controller? How would I do that/alter the routes file?
resources :professors, :labs do
member do
resources :teaching_assistants, except: :index
end
end
get '/professors/id/teaching_assistants' => professors#assistantsindex
get '/labs/id/teaching_assistants' => labs#assistantsindex

Using resources is for creating all the basic RESTful pointers (index/create/read/update/delete). It sounds like your teaching assistants are a 'one off' listing page, in which case you would simply use get to create the route.
Try this:
resources :professors, :labs do
member do
# /professors/id/teaching_assistants > professors#teaching_assistants
# /labs/id/teaching_assistants > labs#teaching_assistants
get 'teaching_assistants'
end
end
# /teaching_assistants
get 'teaching_assistants'

Related

rails routing member and non-member nesting

Two quite similar routing settings really is confusing.
resources :authors do
resources :books
end
and
resources :authors do
member do
resources :books
end
end
As we all know, rails will generate the following routings :
writer_book GET /writers/:writer_id/books/:id(.:format) books#show
and
book GET /writers/:id/books/:id(.:format) books#show
How is this member option useful?
One can just not using member option and set params[:writer_id] in books_controller and be done with it right?
Does this will have a bad affect when the application gets bigger? What are the consequences?
The member and collection methods are meant to add additional RESTful actions to resources
resources :writers do
member do
post :favorite
end
collection do
get :unpublished
end
end
They are not intended for nesting resources
# bad
resources :writers do
member do
resources :books
end
end
# good
resources :writers do
resources :books
end
What are the consequences?
Using member here will result in the route
GET /writers/:id/books/:id(.:format)
Which means that the id param is ambigous! It could be either the id of the book or the author! Not good! Not using member would give us params[:writer_id] which we can use to fetch the parent record.
GET /writers/:writer_id/books/:id(.:format) books#show
See:
Rails Routing from the Outside In

Guidance on organizing routes

I am working on this project that has products and under products I have cars and trucks and each have comments and the ability to vote on both the car model and comments. The car models all work correctly but the trucks model does not have the correct routes. I am thinking it has something to do with having comments shallow, but honestly, I am not sure what I am doing wrong. Any guidance would be appreciated.
resources :products do
resources :cars do
member { post :vote }
resources :car_comments, shallow: true do
member { post :vote }
end
end
resources :trucks do
member { post :vote }
resources :truck_comments, shallow: true do
member { post :vote }
end
end
end
UPDATE
After looking over one of the controller files, I found the error and now the routes work as expected. However, I still feel that my routes look clunky, and since there will be more models, boats, tractors, etc, I dont think the way the routes are written now will hold up.
I believe it is because you are using resources :trucks, when you use the resouces it calls the CRUD methods. if you want certain routes you need to specify them, for example: resources :trucks, only: [:create, :destroy]

How to force custom Rails route to use :id instead of :<model>_id

I defined the following custom Rails route in routes.rb:
resources :projects do
get 'members'
end
This results in the following route (output from rake routes):
project_members GET /projects/:project_id/members(.:format)
What I would like, though, is for the route to map to this instead (change :project_id to :id)
project_members GET /projects/:id/members(.:format)
How can I make that happen?
Is members a nested resource? If so define it as one, and understand that this is why you have :project_id in the route, because :id in a nested resource is used by the final child item - you can't have multiple nested resources all using the same variable to define their id.
resources :projects do
resources :members
end
Add in a third level of nesting and it becomes a bit clearer to explain:
resources :projects do
resources :members do
resources :colours
end
end
With this nesting you could visit app/projects/:project_id/members/:member_id/colours/:id which would be served by the colours controller, which knows that :id defines an instance of that controllers model, and any other named id's belong to other resources.
Otherwise I think you just need to define it as a member method:
resources :projects do
member do
get 'members'
end
end
This tells the route that the action members is a non-resource action belonging to an instance of project, which I think should sort you out, but be sure it's the right thing to do.
See section 2.10 of Rails Routing from the Outside In

Upgrading routes in Rails 3

Currently I have something like this:
resources :books do
collection do
get 'search'
end
end
and my controller name is also "books" and I have a action method called "search" inside it
I would like that "get search" part to also be a resource, kind of like nested resources... but I don't want to break other peoples codes that are using the current route that this generate, so need to update it in a passive way!
resources :books do
collection do
get 'search'
end
resources :searches
end
...if I'm understanding you correctly, that should be what you want. It won't break other routes, just add new ones.
Run rake routes to make sure you have all the routes you want/need.
Use shallow routes nesting like:
resources :books , :shallow => true do
resources :searches
end
Now you will get the following routes:
/books/1 => books_path(1)
/books/1/searches => books_searches_index_path(1)
/searches/2 => searches_path(2)
Similarly you can get separate routing for defined routes like:
get '(:books)/searches', :to => 'books#index'

what is the proper convention for restful routing via namespaces?

Let's say I have a receipts model, and I want to offer a controller action to print one... The un-restful way would be to do:
# receipt_controller.rb
def print
...
end
#routes.rb
resources :receipts do
get :print, :on => :member
end
... The restful way would be:
# receipt_printings_controller.rb
def create
...
end
#routes.rb
resources :receipts
resources :receipt_printings, :only => :create
My question is..... Let's say I wanted to have the following structure:
/app
/controllers
receipts_controller.rb
/receipt
printings_controller.rb
That would mean my class would look like:
class Receipt::PrintingsController < ActiveRecord::Base
def create
...
end
end
But I don't know how to properly route in this context because I still need to be able to do:
receipt_printings_path(123) to get /receipts/123/printings
The only way I know how to accomplish this is to do:
#routes.rb
match "/receipts/:id/printings" => "receipt/printings#create", :as => :receipt_printings
resources :receipts
But, I am wondering if there is a better way?
I think you can do something like this:
resources :receipts do
resources :printings, :controller => "receipt/printings", :only => :create
end
It will generate :
receipt_printings POST /receipts/:receipt_id/printings(.:format) receipt/printings#create
Then to access to your route :
receipt_printings_path(:receipt_id => #receipt.id)
I hope it helps
If i'm right, you need a nested resource, have look in this rails guide
You can use nest routes, but the way I read your question it sounds to me like you want namespaces. Namespaces might look like the following:
resources :receipts
namespace :receipts do
resources :printings
end
This would route /receipts/printings/:id to app/receipt/printings_controller.rb with an id for the printing (not the receipt).
You might really want nested routes. If you want to use the receipt id, and have only one print action (per receipt), you could use a singular resource.
resources :receipts do
resource :printing
end
This will route /receipts/:id/print to app/printings_controller.rb as show.
To organize the printings controller in a namespace, I would leave it out of the routes, because that will try to insert another receipts namespace in the URL. Instead, use,
resources :receipts do
resource :printing, :controller => "receipt/printings"
end
This is how to be RESTful. However, you might not have a RESTful case. Is printing really doing a create? Is it really doing a show or update? If it's a service which doesn't fit into a CRUD operation, then it's time to deviate from the golden path, and go ahead and use a non-RESTful verb.

Resources