Reputation: 6868
Recently I changed a few nested resources in one of my applications to use shallow routing. It's working great and I've been able to simplify my views and controllers.
However, I've been using a path_prefix before:
map.with_options :path_prefix => "blog" do |blog|
blog.resources :posts do |posts|
posts.resources :comments
end
end
Notice, that all routes are prefixed with "/blog" as expected.
# $ rake routes
# posts GET /blog/posts(.:format) {:controller=>"posts", :action=>"index"}
# POST /blog/posts(.:format) {:controller=>"posts", :action=>"create"}
# new_post GET /blog/posts/new(.:format) {:controller=>"posts", :action=>"new"}
# edit_post GET /blog/posts/:id/edit(.:format) {:controller=>"posts", :action=>"edit"}
# post GET /blog/posts/:id(.:format) {:controller=>"posts", :action=>"show"}
# PUT /blog/posts/:id(.:format) {:controller=>"posts", :action=>"update"}
# DELETE /blog/posts/:id(.:format) {:controller=>"posts", :action=>"destroy"}
# post_comments GET /blog/posts/:post_id/comments(.:format) {:controller=>"comments", :action=>"index"}
# POST /blog/posts/:post_id/comments(.:format) {:controller=>"comments", :action=>"create"}
# new_post_comment GET /blog/posts/:post_id/comments/new(.:format) {:controller=>"comments", :action=>"new"}
# edit_post_comment GET /blog/posts/:post_id/comments/:id/edit(.:format) {:controller=>"comments", :action=>"edit"}
# post_comment GET /blog/posts/:post_id/comments/:id(.:format) {:controller=>"comments", :action=>"show"}
# PUT /blog/posts/:post_id/comments/:id(.:format) {:controller=>"comments", :action=>"update"}
# DELETE /blog/posts/:post_id/comments/:id(.:format) {:controller=>"comments", :action=>"destroy"}
The new routing configuration looks like this:
map.with_options :path_prefix => "blog", :shallow => true do |blog|
blog.resources :posts do |posts|
posts.resources :comments
end
end
Now, the "/blog" prefix is missing in some of my routes.
# $ rake routes
# posts GET /blog/posts(.:format) {:controller=>"posts", :action=>"index"}
# POST /blog/posts(.:format) {:controller=>"posts", :action=>"create"}
# new_post GET /blog/posts/new(.:format) {:controller=>"posts", :action=>"new"}
# edit_post GET /posts/:id/edit(.:format) {:controller=>"posts", :action=>"edit"}
# post GET /posts/:id(.:format) {:controller=>"posts", :action=>"show"}
# PUT /posts/:id(.:format) {:controller=>"posts", :action=>"update"}
# DELETE /posts/:id(.:format) {:controller=>"posts", :action=>"destroy"}
# post_comments GET /posts/:post_id/comments(.:format) {:controller=>"comments", :action=>"index"}
# POST /posts/:post_id/comments(.:format) {:controller=>"comments", :action=>"create"}
# new_post_comment GET /posts/:post_id/comments/new(.:format) {:controller=>"comments", :action=>"new"}
# edit_comment GET /comments/:id/edit(.:format) {:controller=>"comments", :action=>"edit"}
# comment GET /comments/:id(.:format) {:controller=>"comments", :action=>"show"}
# PUT /comments/:id(.:format) {:controller=>"comments", :action=>"update"}
# DELETE /comments/:id(.:format) {:controller=>"comments", :action=>"destroy"}
I'm looking for a solution to get the prefixes back for all routes. I know that it's working with namespaces (map.namespace :blog do
), but I want to prevent refactoring all my controllers/views/tests to actually use namespaces.
All code samples are tested with Rails version 2.3.2 and Ruby 1.8.7.
Upvotes: 4
Views: 3304
Reputation: 15180
the documentation seems to indicate this exact behavior is by design:
:shallow - If true, paths for nested resources which reference a specific member (ie. those with an :id parameter) will not use the parent path prefix or name prefix.
(from http://api.rubyonrails.org/classes/ActionController/Resources.html#M000501)
Since using the :shallow option will cause your :path_prefix to be ignored in some cases, if you must always have this prefix you should consider removing the :shallow option. Here's an alternate solution that appears to do what you need:
map.with_options :path_prefix => "blog" do |blog|
blog.resources :posts do |posts|
posts.resources :comments, :only => [:index, :create, :new]
end
blog.resources :comments, :except => [:index, :create, :new]
end
Resulting in these routes:
# posts GET /blog/posts {:controller=>"posts", :action=>"index"}
# POST /blog/posts {:controller=>"posts", :action=>"create"}
# new_post GET /blog/posts/new {:controller=>"posts", :action=>"new"}
# edit_post GET /blog/posts/:id/edit {:controller=>"posts", :action=>"edit"}
# post GET /blog/posts/:id {:controller=>"posts", :action=>"show"}
# PUT /blog/posts/:id {:controller=>"posts", :action=>"update"}
# DELETE /blog/posts/:id {:controller=>"posts", :action=>"destroy"}
# post_comments GET /blog/posts/:post_id/comments {:controller=>"comments", :action=>"index"}
# POST /blog/posts/:post_id/comments {:controller=>"comments", :action=>"create"}
# new_post_comment GET /blog/posts/:post_id/comments/new {:controller=>"comments", :action=>"new"}
# edit_comment GET /blog/comments/:id/edit {:controller=>"comments", :action=>"edit"}
# comment GET /blog/comments/:id {:controller=>"comments", :action=>"show"}
# PUT /blog/comments/:id {:controller=>"comments", :action=>"update"}
# DELETE /blog/comments/:id {:controller=>"comments", :action=>"destroy"}
Hope this helps!
Upvotes: 6
Reputation: 2948
Probably the easiest solution would not be to use :shallow option but create the same routes with additional resource definition:
map.with_options :path_prefix => "blog" do |blog|
blog.resources :posts do |posts|
posts.resources :comments, :only => [:index, :create, :new]
end
end
map.resources :comments, :path_prefix => "blog",
:except => [:index, :create, :new]
which gives the following routes definitions:
# $ rake routes
# posts GET /blog/posts(.:format) {:action=>"index", :controller=>"posts"}
# POST /blog/posts(.:format) {:action=>"create", :controller=>"posts"}
# new_post GET /blog/posts/new(.:format) {:action=>"new", :controller=>"posts"}
# edit_post GET /blog/posts/:id/edit(.:format) {:action=>"edit", :controller=>"posts"}
# post GET /blog/posts/:id(.:format) {:action=>"show", :controller=>"posts"}
# PUT /blog/posts/:id(.:format) {:action=>"update", :controller=>"posts"}
# DELETE /blog/posts/:id(.:format) {:action=>"destroy", :controller=>"posts"}
# post_comments GET /blog/posts/:post_id/comments(.:format) {:action=>"index", :controller=>"comments"}
# POST /blog/posts/:post_id/comments(.:format) {:action=>"create", :controller=>"comments"}
# new_post_comment GET /blog/posts/:post_id/comments/new(.:format) {:action=>"new", :controller=>"comments"}
# edit_comment GET /blog/comments/:id/edit(.:format) {:action=>"edit", :controller=>"comments"}
# comment GET /blog/comments/:id(.:format) {:action=>"show", :controller=>"comments"}
# PUT /blog/comments/:id(.:format) {:action=>"update", :controller=>"comments"}
# DELETE /blog/comments/:id(.:format) {:action=>"destroy", :controller=>"comments"}
Upvotes: 5