This project is archived and is in readonly mode.

#3170 ✓invalid
Jose Prado

Routing conflicts with shallow routes

Reported by Jose Prado | September 9th, 2009 @ 07:56 AM

I'm quite new to Rails (less than a week in) and I've run into a snag.

I have three models. User has many Groups through Memberships. Group has many Users through Memberships. Membership belongs to Users and Groups.

Everything was working fine until I tried to use the shallow routes option. I've set up RESTful routing using:

map.resources :users, :has_many => :groups, :shallow => true
map.resources :groups, :has_many => :users, :shallow => true

The User routes work fine but now the Group routes are broken since I can't access /groups/new anymore. A call of "rake routes" clearly shows the problem (I took out the non-GET routes for simplicity and added text because the Lighthouse syntax parser butchers lines with space at the beginning.):

user_groups     GET /users/:user_id/groups(.:format)        {:controller=>"groups", :action=>"index"}
new_user_group  GET /users/:user_id/groups/new(.:format)    {:controller=>"groups", :action=>"new"}
edit_group      GET /groups/:id/edit(.:format)              {:controller=>"groups", :action=>"edit"}
group           GET /groups/:id(.:format)                   {:controller=>"groups", :action=>"show"}
users           GET /users(.:format)                        {:controller=>"users", :action=>"index"}
new_user        GET /users/new(.:format)                    {:controller=>"users", :action=>"new"}
edit_user       GET /users/:id/edit(.:format)               {:controller=>"users", :action=>"edit"}
user            GET /users/:id(.:format)                    {:controller=>"users", :action=>"show"}
group_users     GET /groups/:group_id/users(.:format)       {:controller=>"users", :action=>"index"}
new_group_user  GET /groups/:group_id/users/new(.:format)   {:controller=>"users", :action=>"new"}
new_group_user  GET /users/:id/edit(.:format)               {:controller=>"users", :action=>"edit"}
new_group_user  GET /users/:id(.:format)                    {:controller=>"users", :action=>"show"}
groups          GET /groups(.:format)                       {:controller=>"groups", :action=>"index"}
new_group       GET /groups/new(.:format)                   {:controller=>"groups", :action=>"new"}
new_group       GET /groups/:id/edit(.:format)              {:controller=>"groups", :action=>"edit"}
new_group       GET /groups/:id(.:format)                   {:controller=>"groups", :action=>"show"}

The route "group GET /groups/:id(.:format) {:controller=>"groups", :action=>"show"}" takes precedence over the "new_group GET /groups/new(.:format) {:controller=>"groups", :action=>"new"}" route so it seems that "new" is interpreted as the :id parameter.

If I remove the shallow routes option and run "rake routes" again, we get similar routing, but in this case, the /groups/new path works as expected. Here's the relevant sections from these routes:

user_groups     GET /users/:user_id/groups(.:format)            {:controller=>"groups", :action=>"index"}
new_user_group  GET /users/:user_id/groups/new(.:format)        {:controller=>"groups", :action=>"new"}
edit_user_group GET /users/:user_id/groups/:id/edit(.:format)   {:controller=>"groups", :action=>"edit"}
user_group      GET /users/:user_id/groups/:id(.:format)        {:controller=>"groups", :action=>"show"}


groups GET /groups(.:format) {:controller=>"groups", :action=>"index"} new_group GET /groups/new(.:format) {:controller=>"groups", :action=>"new"} edit_group GET /groups/:id/edit(.:format) {:controller=>"groups", :action=>"edit"} group GET /groups/:id(.:format) {:controller=>"groups", :action=>"show"}

Looking at these routes, it seems that when the nested routes get shortened with the shallow routes option, they end up becoming higher precedence routes which kill the natural Group routes. More specifically, route "user_group GET /users/:user_id/groups/:id(.:format) {:controller=>"groups", :action=>"show"}" becomes route "group GET /groups/:id(.:format) {:controller=>"groups", :action=>"show"}" which is causing the conflict.

So again, Rails beginner here so I'm not sure if this is how it's supposed to work, but it doesn't seem like expected behavior to me. Any tips/thoughts?

Comments and changes to this ticket

  • Pete Campbell

    Pete Campbell November 6th, 2009 @ 11:21 PM

    This doesn't seem to me to be a bug, routes are executed in order and I think your analysis is correct. One solution is to only generate the nested resources for :users, eg.

    map.resources :users do |users|
    users.resources :groups, :shallow => true, :only => [:index, :new] end

    This will generate only the /users/:user_id/groups and /users/:user_id/groups/new routes, so all /groups routes will fall through to the map.resources :groups, :shallow => true routes

  • Mike Riley

    Mike Riley July 29th, 2010 @ 03:37 PM

    • State changed from “new” to “invalid”
    • Importance changed from “” to “”

    Hello,

    I am going to mark this as invalid based on Pete's reply. If you are still having issues with configuring and setting up your routes, you could also ask at http://www.railsforum.com/ or http://www.ruby-forum.com/forum/3 for further help. I have had good luck with those sites.

    Mike Riley

Create your profile

Help contribute to this project by taking a few moments to create your personal profile. Create your profile »

<h2 style="font-size: 14px">Tickets have moved to Github</h2>

The new ticket tracker is available at <a href="https://github.com/rails/rails/issues">https://github.com/rails/rails/issues</a>

People watching this ticket

Pages