Rails 4 [最佳实践]嵌套资源和浅层:真实

Ero*_*lin 27 api rest ruby-on-rails nested-routes ruby-on-rails-4

以下帖子基于Rails 4.

我实际上正在寻找关于多个嵌套资源(超过1个)的良好最佳实践,并且选项浅:true.

首先在我的路线中,有这样的:

resources :projects do 
  resources :collections
end
Run Code Online (Sandbox Code Playgroud)

相关的路线是:

    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
Run Code Online (Sandbox Code Playgroud)

我在文档中读到了嵌套资源的限制:

资源不应该嵌套超过1级深度.

来源:http://guides.rubyonrails.org/routing.html#limits-to-nesting 好的.然后,就像文件说的那样,我将在我的路线中使用"浅".

shallow do
  resources :projects do 
    resources :collections
  end
end
Run Code Online (Sandbox Code Playgroud)

相关的路线是:

   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
Run Code Online (Sandbox Code Playgroud)

我看到的主要区别是收藏品的"展示",这个:

collection GET    /collections/:id(.:format)                      collections#show
Run Code Online (Sandbox Code Playgroud)

所以如果我是对的,那么集合的show动作的链接是:

<%= link_to 'Show", collection_path(collection)%>
Run Code Online (Sandbox Code Playgroud)

并应该返回这样的内容:" http://example.com/collections/1 "

但是!2件事:

  • 这不起作用.我正在改为" http://example.com/projects/1 ".WTF?
  • 即使它正在工作,它实际上也很糟糕,因为我松开了REST基础,说"集合是项目的子项,那么url应该是"localhost/project/1/collections/1"

如果松开Rest动作的巨大优势,我不明白浅层的兴趣是什么.有什么兴趣?放松"表演"行动的兴趣是什么?我已经把它发布到了SO,但我得到的唯一评论是"这是正常的".WTF?这是从其他API"移除"操作的正常行为?

我在一个中立项目上重现了这个问题,以确保我没有做错什么,同样的问题也发生了.所以,是的,帮助者使用浅层可能很方便,但对其余部分来说并不方便,你放弃了"一个集合嵌套到一个项目,所以这反映在URL中"的所有兴趣.

我不知道是否有另一种方法可以做到这一点,浅薄的是允许帮助者更多的灵活性,但是它的休息是否合规是错误的.那么,有没有机会让"助手"工作(拥有"nested3_path(collection)"而不是"nested1_nested2_nested3([nested1.nested2.nested3,nested1.nested2,nested1])"非常棒,并保持" url part"并保持"nested1/123/nested2/456/nested3/789?

谢谢 !

Car*_*III 20

我不相信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
Run Code Online (Sandbox Code Playgroud)

但是,为每个资源手动执行操作非常麻烦.


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

避免深度嵌套的一种方法(如上所述)是生成在父级下作用域的集合操作,以便了解层次结构,但不嵌套成员操作.换句话说,仅构建具有最少量信息的路由以唯一地标识资源

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

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


ace*_*des 10

由于存在idfor a Collection,因此除了indexcreateactions 之外,在项目下嵌套路径是多余的.

有一个关于URL的规则,其中只有一个URL给GET(200)一个给定的资源,如果还有其他URL你应该重定向到它.所以你可能有一个/projects/:id/collections/:collection_id重定向到的路由/collections/:collection_id.

在您的情况下,Collection与项目绑定,但对于所有关系而言并不一定如此.一旦拥有了,:collection_id您就不需要引用它的上下文Project来访问它.