2014-02-19 67 views
27

以下职位是基于on Rails的4轨道4 [最佳做法]嵌套资源和浅:真

实际上,我在寻找有关的多个嵌套资源良好的最佳实践(大于1),和选项浅:真。

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

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 

我有关嵌套资源的限制的文件中读取资源不应该嵌套超过1级。

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

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”。 WTF?
  • 即使是工作,它实际上是非常糟糕的,因为我失去了REST基本是说:“收藏是项目的孩子,那么URL应该是‘本地主机/项目/ 1 /收藏/ 1’

我不明白什么是浅薄的利益,如果它是放松休息行动的巨大优势。什么是兴趣?什么是放松“显示”行动的兴趣?我已经发布到SO,但唯一的评论我得到的是“这是正常的东西。”跆拳道?在这是一个正常的行为,以“从其他API删除”行动?

我转载了一个中性项目的问题,以确保我没有做有问题,并发生同样的问题。所以,对于辅助者来说,使用浅度可能会比较方便,但对于其他人来说,这并不方便,因为您放弃了“一个集合嵌套到一个项目中的所有兴趣,所以这反映在URL中”。

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

谢谢!

+0

您是否尝试过重新启动服务器以使路由生效? 据商务部 '资源:帖子,浅:真正做 资源:评论 end' 会产生 '资源:帖子做 资源:评论,除了:[:显示,编辑,:更新, :destroy] end 资源:评论,只:[:显示,:编辑,:更新,:销毁]' 你好像在做什么 – jamesy829

+0

确实必须重启服务器才能使路由生效。 – 0112

回答

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 

但是,这将是非常麻烦的每个资源做手工。


我觉得用shallow路线背后的想法是最好的文档总结:避免深度嵌套(如上推荐)

的一种方法是产生 范围的收集行动在父项下,以获得层次结构的感知 ,但不嵌套成员操作。换句话说, 只有建立与信息 最小量的路由唯一地标识资源

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

因此,尽管这可能不是REST规范(像你说的),你不会丢失任何信息,因为每个资源都可以唯一标识,并且您可以在假设您的关联设置正确的情况下恢复层级。

+0

虽然它没有内置到Rails,[继承资源](https://github.com/josevalim/inherited_resources)(IR)有嵌套和帮手,可能有帮助。如果仅仅是少数情况下使用IR,它可能是好的,而不是使用IR,它也可以根据你的需要限制或复杂控制器的实现/调试。 –

2

水平

,你必须在你的嵌套的资源只能用1级的概念是唯一真正适用于系统的设计:

相应的路线助手将publisher_magazine_photo_url, 要求您在所有三个级别指定对象。事实上,这种 情况混乱,以至于通过了Jamis巴克 一个流行的文章提出了拇指良好的Rails设计的原则:

相信的Rails仍然可以处理多个层面,虽然它不是从可用性的角度来看

推荐

虽然我见过浅以前用过,我从来没有用它自己

从看documentation,它似乎很浅,有一个相当模糊的目的(我不知道它为什么在那里)。问题是你没有公开传递post_id参数到你的控制器,让你加载collection没有一个重要的参数

我会猜测(这只是猜测),目的是通过你的参数需要在幕后,所以你留下了一个公共“浅”路线:

#config/routes.rb 
resources :projects do 
    resources :collections, shallow: true 
end 

我会想象你会得到一个网址助手是这样的:

collection_path(project.id, collection.id) 

这会出来的domain.com/collection/2

+0

是的,你是正确的路线,但这对我的问题没有多大帮助=/ – Erowlin

10

因为有一个Collection是一个id,它是多余的嵌套项目下的路径除了indexcreate行动。

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

在你的情况下,一个集合与一个项目绑定,但这对于所有的关系并不一定是正确的。一旦你有了:collection_id,你就不需要参考Project的上下文来访问它。

+0

是的!谢谢!我一直在寻找浅层路线目的的基本解释!文档中的假设是:您已经知道这一点。从其他一些答案来看,其他很多人都不知道!你说的是,如果你是例如编辑一个评论:id,它没有任何意义嵌套在项目下,因为评论:ID是独立于项目ID。浅薄只是清理路线来反映这一点。 – Colin

2

虽然它可能会使事情复杂化,如果您只需要某些型号,可能需要检查Inherited Resources(IR)。它支持资源嵌套,多态属于它,并且可以自动生成你正在寻找的较短的路径和url帮助器方法。你没有听说IR的原因是它的原作者和一些其他开发者已经放弃了它,因为在扩展你的控制器时出现了复杂问题。但是,它仍然有一个社区,我们试图扩展它更多,并更多地关注使用Irie控制器扩展的简易性。

Rails中的“最佳实践”取决于您与谁交谈。

Rails传统上主要针对(非嵌套)资源的基本CRUD。是的,它允许检索和更新嵌套的资源,但假设不会经常发生。

但是,Rails社区已经出现的方法是ActiveModel::Serializers/json-api方法。在这种情况下,通常不会发生多个级别的资源嵌套,并且嵌套的资源是链接列表或侧载的小型资源的子版本,然后您可以在该资源上查询以获取更多数据。这也被Ember/Ember Data所包含。

还有roar和一些其他项目旨在实现一些更接近于他们对Roy Fielding最初的REST愿景的理解。

我认为这取决于你的设计和你需要什么。如果效率是一个目标,那么额外的时间发展为明确的并且筑巢更多的时间可能会得到回报。例如,我们目前使用AngularJSIrie。但每一个他自己。

至于最后一点,请务必避免在查询中使用includes(...)(或类似的)进行n + 1查找,否则所有嵌套操作都会影响性能。

1

From this answer它似乎很浅薄的路线有点违抗Rails,IMO的惯例。

我认为你不需要显式路径助手来显示路径。 link_to助手应该能够从对象的to_param方法中推断出它。

#your helper becomes 
link_to "show", collection 

如果以上述方式使用助手,则可能需要将父资源的嵌套ID传递给助手。

link_to "show", collection_path([project, collection])