Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Routing nested resources in Rails 3

I have a pretty common case for nested routes, I feel like, that looks something like this (in some sort of pseudonotation):

'/:username/photos' => Show photos for User.find_by_username '/photos' => Show photos for User.all 

In a nutshell: I have users. They have photos. I want to be able to show their photos on their page. I also want to be able to show all photos, regardless of the user. I'd like to keep my routes RESTful and using the built-in resource methods feels like the right way to do it.


Option 1 for doing this is to have PhotosController#index use a conditional to check which params are given and get the list of photos and set the view (different for a user's photos than for all photos). It's even easy to route it:

resources :photos, :only => [:index] scope ':/username' do   resources :photos end 

Boom. It'd seem like Rails was setup for this. After the routes, though, things get more complicated. That conditional back in the PhotosController#index action is just getting more and more bloated and is doing an awful lot of delgation. As the application grows and so do the number of ways I want to show photos, it is only going to get worse.

Option 2 might be to have a User::PhotosController to handle user photos, and a PhotosController to handle showing all photos.

resources :photos, :only => [:index] namespace :user, :path => '/:username' do   resources :photos end 

That generates the following routes:

           photos GET    /photos(.:format)                    {:action=>"index", :controller=>"photos"}       user_photos GET    /:username/photos(.:format)          {:action=>"index", :controller=>"user/photos"}                   POST   /:username/photos(.:format)          {:action=>"create", :controller=>"user/photos"}    new_user_photo GET    /:username/photos/new(.:format)      {:action=>"new", :controller=>"user/photos"}   edit_user_photo GET    /:username/photos/:id/edit(.:format) {:action=>"edit", :controller=>"user/photos"}        user_photo GET    /:username/photos/:id(.:format)      {:action=>"show", :controller=>"user/photos"}                   PUT    /:username/photos/:id(.:format)      {:action=>"update", :controller=>"user/photos"}                   DELETE /:username/photos/:id(.:format)      {:action=>"destroy", :controller=>"user/photos"} 

This works pretty well, I think, but everything is under a User module and I feel like that might end up causing problems when I integrate it with other things.

Questions

  • Does anybody have experience with something like this?
  • Can anybody share a better way of handling this?
  • Any additional pros and cons to consider with either of these options?

Update: I've gone ahead implementing Option 2 because it feels cleaner allowing Rails' logic to work rather than overriding it. So far things are going well, but I also needed to rename my namespace to :users and add an :as => :user to keep it from clashing with my User model. I've also overridden the to_param method on the User model to return the username. Path helpers still work this way, too.

I'd still appreciate feedback on this method. Am I doing things the expected way, or am I misusing this functionality?

like image 889
coreyward Avatar asked Feb 17 '11 04:02

coreyward


People also ask

What is a nested resource rails?

Rails Nested Resources Nested routes are another way of capturing these relationships through your routing. This means that our URLs will look aesthetically pleasing and not a random string of numbers and characters. resources :coffees do. resources :reviews, only: [:new, :index, :show]

What are rails resource routes?

Any object that you want users to be able to access via URI and perform CRUD (or some subset thereof) operations on can be thought of as a resource. In the Rails sense, it is generally a database table which is represented by a model, and acted on through a controller.

How many types of routes are there in Rails?

Rails RESTful Design which creates seven routes all mapping to the user controller. Rails also allows you to define multiple resources in one line.


1 Answers

Have you considered using a shallow nested route in this case?

Shallow Route Nesting At times, nested resources can produce cumbersome URLs. A solution to this is to use shallow route nesting:

resources :products, :shallow => true do   resources :reviews end 

This will enable the recognition of the following routes:

/products/1 => product_path(1) /products/1/reviews => product_reviews_index_path(1) /reviews/2 => reviews_path(2) 
like image 101
MattMcKnight Avatar answered Oct 04 '22 19:10

MattMcKnight