在Rails 3中路由嵌套资源 [英] 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
简而言之:我有用户。他们有照片。我希望能够在他们的页面上显示他们的照片。我也希望能够显示所有照片,无论用户是谁。我想使我的路由保持REST风格,并使用内置的资源
方法似乎是正确的方法。
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.
选项1 的目的是使PhotosController#index使用条件检查给出的参数并获取照片列表和设置视图(用户照片与所有照片不同)。路由起来甚至很容易:
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
景气。 似乎就像为此设置了Rails。经过路线之后,事情变得更加复杂。 PhotosController#index操作中的条件返回变得越来越肿,并且进行了大量的讨论。随着应用程序的增长以及我想要显示照片的方式的增多,它只会变得更糟。
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.
选项2 将拥有一个User :: PhotosController处理用户照片,并使用PhotosController处理显示所有照片。
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
以下路线:
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"}
我认为这很好用,但是所有内容都在User模块下,当我将其与其他东西集成时,我觉得那可能最终会导致问题。
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.
- 有人有这样的经历吗?
- 任何人都可以分享一种更好的方式来处理此问题吗?
- 使用这些选项中的任何其他利弊?
更新:我继续实施方案2,因为它感觉更干净,允许Rails的逻辑起作用而不是覆盖它。到目前为止,一切进展顺利,但我还需要将命名空间重命名为:users
并添加:as => :user
,以防止它与我的 User
模型冲突。我还重写了 User
模型上的 to_param
方法以返回用户名。路径助手也仍然以这种方式工作。
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.
我仍然很感谢这种方法的反馈。我是按预期的方式执行操作,还是滥用此功能?
推荐答案
做到这一点的最佳方法取决于应用程序,但在我的情况下肯定是选项B。使用命名空间路由,我可以使用模块以非常干净的方式将不同的问题分离到不同的控制器中。我还使用特定于名称空间的控制器向特定名称空间中的所有控制器添加共享功能(例如,添加before_filter来检查名称空间中所有资源的身份验证和权限)。
The best way to do this depends on the application, but in my case it is certainly Option B. Using namespaced routes I'm able to use a module to keep different concerns separated out into different controllers in a very clean way. I'm also using a namespace-specific controller to add shared functionality to all controllers in a particular namespace (adding, for example, a before_filter to check for authentication and permission for all resources in the namespace).
这篇关于在Rails 3中路由嵌套资源的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!