Ruby-on-rails 在 Rails 3 中路由嵌套资源

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5025050/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 00:27:04  来源:igfitidea点击:

Routing nested resources in Rails 3

ruby-on-railsrubyruby-on-rails-3routing

提问by coreyward

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 resourcemethods feels like the right way to do it.

简而言之:我有用户。他们有照片。我希望能够在他们的页面上显示他们的照片。我还希望能够显示所有照片,而不管用户是谁。我想让我的路由保持 RESTful 并且使用内置resource方法感觉是正确的方法。



Option 1for 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:

这样做的选项 1是让 PhotosController#index 使用条件来检查给出了哪些参数并获取照片列表并设置视图(用户照片与所有照片不同)。路由它甚至很容易:

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

Boom. It'd seemlike 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.

繁荣。它会看起来像Rails的是设置此。然而,在路线之后,事情变得更加复杂。在 PhotosController#index 操作中返回的条件变得越来越臃肿并且正在做大量的委托。随着应用程序的增长以及我想要显示照片的方式数量的增加,情况只会变得更糟。

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

选项 2可能是使用 User::PhotosController 来处理用户照片,使用 PhotosController 来处理显示所有照片。

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 :usersand add an :as => :userto keep it from clashing with my Usermodel. I've also overridden the to_parammethod on the Usermodel to return the username. Path helpers still work this way, too.

更新:我已经开始实施选项 2,因为它让 Rails 的逻辑工作而不是覆盖它感觉更干净。到目前为止一切进展顺利,但我还需要将我的命名空间重命名为:users并添加一个:as => :user以防止它与我的User模型发生冲突。我还覆盖了模型to_param上的方法User以返回用户名。路径助手仍然以这种方式工作。

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

我仍然很感激对此方法的反馈。我是按照预期的方式做事,还是滥用了这个功能?

采纳答案by coreyward

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).

执行此操作的最佳方法取决于应用程序,但在我的情况下,它肯定是选项 B。使用命名空间路由我能够使用一个模块以非常干净的方式将不同的关注点分离到不同的控制器中。我还使用特定于命名空间的控制器向特定命名空间中的所有控制器添加共享功能(例如,添加 before_filter 以检查命名空间中所有资源的身份验证和权限)。

回答by MattMcKnight

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:

浅层路由嵌套 有时,嵌套资源会产生麻烦的 URL。对此的解决方案是使用浅层路由嵌套:

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)

回答by Jimmy Cuadra

I did something similar to this in one of my apps. You're on the right track. What I did was declare nested resources, and build the query using the flexible arel-based syntax of Active Record in Rails 3. In your case it might look something like this:

我在我的一个应用程序中做了类似的事情。你在正确的轨道上。我所做的是声明嵌套资源,并使用 Rails 3 中 Active Record 灵活的基于 arel 的语法构建查询。在您的情况下,它可能如下所示:

# config/routes.rb
resources :photos, :only => :index
resources :users do
  resources :photos
end

# app/controllers/photos_controller.rb
def index
  @photos = Photo.scoped
  @photos = @photos.by_user(params[:user_id]) if params[:user_id]
  # ...
end

回答by Martijn

You could define a seperate route for getting the photos for one user like so:

您可以定义一个单独的路线来为一个用户获取照片,如下所示:

get '(:username)/photos', :to => 'photos#index'

But I would advise just using the nested resource that Jimmy posted above since that is the most flexible solution.

但我建议只使用 Jimmy 在上面发布的嵌套资源,因为这是最灵活的解决方案。

回答by Arthur Corenzan

Example::Application.routes.draw do
  resources :accounts, :path => '' do
    resources :projects, :path => '', :except => [:index]
  end
end

Got the example from: http://jasoncodes.com/posts/rails-3-nested-resource-slugs

从以下示例中获取:http: //jasoncodes.com/posts/rails-3-nested-resource-slugs

Just applied that in my current project.

刚刚在我当前的项目中应用了它。