Skip to main content
 首页 » 编程设计

ruby-on-rails之Rails 4 【最佳实践】嵌套资源和浅层 : true

2024年10月25日20think

以下帖子基于 Rails 4。
我目前正在寻找关于多个嵌套资源(超过 1 个)的最佳实践,以及选项shallow: true。
最初在我的 route ,有这样的:

resources :projects do  
  resources :collections 
end 
相关的路线是:
    project_collections GET    /projects/:project_id/collections(.:format)          collections#index 
                        POST   /projects/:project_id/collections(.:format)          collections#create 
 new_project_collection GET    /projects/:project_id/collections/new(.:format)      collections#new 
edit_project_collection GET    /projects/:project_id/collections/:id/edit(.:format) collections#edit 
     project_collection GET    /projects/:project_id/collections/:id(.:format)      collections#show 
                        PATCH  /projects/:project_id/collections/:id(.:format)      collections#update 
                        PUT    /projects/:project_id/collections/:id(.:format)      collections#update 
                        DELETE /projects/:project_id/collections/:id(.:format)      collections#destroy 
               projects GET    /projects(.:format)                                  projects#index 
                        POST   /projects(.:format)                                  projects#create 
            new_project GET    /projects/new(.:format)                              projects#new 
           edit_project GET    /projects/:id/edit(.:format)                         projects#edit 
                project GET    /projects/:id(.:format)                              projects#show 
                        PATCH  /projects/:id(.:format)                              projects#update 
                        PUT    /projects/:id(.:format)                              projects#update 
                        DELETE /projects/:id(.:format)                              projects#destroy 
我在 documentation 中阅读了有关嵌套资源限制的信息:

Resources should never be nested more than 1 level deep.


好的。然后,就像文档所说的那样,我将在我的 route 使用“浅”。
shallow do 
  resources :projects do  
    resources :collections 
  end 
end 
相关的路线是:
   project_collections GET    /projects/:project_id/collections(.:format)     collections#index 
                       POST   /projects/:project_id/collections(.:format)     collections#create 
new_project_collection GET    /projects/:project_id/collections/new(.:format) collections#new 
       edit_collection GET    /collections/:id/edit(.:format)                 collections#edit 
            collection GET    /collections/:id(.:format)                      collections#show 
                       PATCH  /collections/:id(.:format)                      collections#update 
                       PUT    /collections/:id(.:format)                      collections#update 
                       DELETE /collections/:id(.:format)                      collections#destroy 
              projects GET    /projects(.:format)                             projects#index 
                       POST   /projects(.:format)                             projects#create 
           new_project GET    /projects/new(.:format)                         projects#new 
          edit_project GET    /projects/:id/edit(.:format)                    projects#edit 
               project GET    /projects/:id(.:format)                         projects#show 
                       PATCH  /projects/:id(.:format)                         projects#update 
                       PUT    /projects/:id(.:format)                         projects#update 
                       DELETE /projects/:id(.:format)                         projects#destroy 
我看到的主要区别是集合的“展示”,这个特定的:
collection GET    /collections/:id(.:format)                      collections#show 
因此,如果我是对的,则集合的显示操作的链接是:
<%= link_to 'Show", collection_path(collection)%> 
并且应该返回如下内容:“http://example.com/collections/1”
但 ! 2件事:
  • 这不起作用。我得到的是“http://example.com/projects/1”。
  • 即使它在工作,但实际上 IMO 非常糟糕,因为我失去了 REST 基础,上面说“集合是项目的子项,那么 url 应该是”localhost/project/1/collections/1”

  • 如果我失去了 Rest Action 的大优势,我不明白浅层的兴趣是什么。以及取消“表演”行动的兴趣是什么?我已经将此发布到 SO,但我得到的唯一评论是“这是正常的”。我不认为这是从其余 API 中“删除”操作的正常行为?
    是的,帮助者使用浅层可能很方便,但对于其他人来说一点也不方便,你失去了“一个集合嵌套到一个项目,所以这反射(reflect)在 URL 中”的所有兴趣。
    我不知道是否有另一种方法可以做到这一点,确实,浅层允许助手具有更大的灵活性,但它符合 REST 是错误的。那么,是否有机会让“助手”工作(拥有“nested3_path(collection)”而不是“nested1_nested2_nested3([nested1.nested2.nested3,nested1.nested2,nested1])”,并保持“网址部分“nested1/123/nested2/456/nested3/789”?

    请您参考如下方法:

    我不相信 Rails 提供任何内置方式让 URL 使用完整的层次结构(例如 /projects/1/collections/2 ),但也有快捷方式助手(例如 collection_path 而不是 project_collection_path )。

    如果你真的想这样做,你可以像下面这样推出你自己的自定义助手:

    def collection_path(collection) 
      # every collection record should have a reference to its parent project 
      project_collection_path(collection.project, collection) 
    end 
    

    但是对于每个资源手动执行会非常麻烦。

    我认为使用 shallow 背后的想法路线最好由文档总结:

    One way to avoid deep nesting (as recommended above) is to generate the collection actions scoped under the parent, so as to get a sense of the hierarchy, but to not nest the member actions. In other words, to only build routes with the minimal amount of information to uniquely identify the resource



    来源: http://guides.rubyonrails.org/routing.html#shallow-nesting

    因此,虽然这可能不符合 REST 标准(如您所说),但您不会丢失任何信息,因为每个资源都可以被唯一标识,并且假设您的关联设置正确,您可以返回层次结构。