使用单个标识符RESTful嵌套资源路由

在我的Rails应用程序中,我在两个实体之间有一个相当标准的has_many关系。 Foo有零个或多个Bars ; 一个Bar恰好属于一个Foo 。 Foo和Bar都由单个整数ID值标识。 这些值在所有各自的实例中都是唯一的。

Bar的存在依赖于Foo:拥有没有Foo的Bar是没有意义的。

有两种方法可以RESTful地引用这些类的实例。 给定Foo.id为“100”且Bar.id为“200”:

  1. 通过他们自己的“顶级”URL路由引用每个Foo和Bar,如下所示:

    • /富/ 100
    • /棒/ 200
  2. 参考栏通过其Foo实例作为嵌套资源:

    • /富/ 100
    • /富/ 100 /酒吧/ 200

我喜欢#2中的嵌套路由,因为它更接近地表示实体之间的实际依赖关系。 然而,它似乎涉及很多额外的工作,收益很少。 假设我知道一个特定的酒吧,我不需要被告知特定的Foo; 我可以从Bar本身那里得到它。 事实上,我可能应该在任何地方validation路由Foo(这样你就不能做/ foo / 150 / bar / 200,假设Bar 200没有分配给Foo 150)。 最终,我看不出这给我带来了什么。

那么,是否有任何其他论据支持或反对这两种路由方案?

澄清点

我主要关注特定Bars的RESTful更新/显示/删除。 为了获得特定Foo的Bar列表(通常是Rails中的“索引”动作),有一个嵌套路由,如/ foo / 100 / bar,这是完全合理的。 这条路线上的页面可以很容易地链接到/ bar / x和/ foo / 100 / bar / x。

你正在寻找浅薄的路线。 正如您所指出的那样,由于您直接定位所需的记录,因此无需为创建,更新等内容设置深层嵌套路径。

我从来没有真正完成浅层路由工作,所以我将传递一个railscast剧集,其中Ryan Bates解释它可能比我更好: 139嵌套资源 。

编辑:您可以阅读有关路由3.8.4的指南 。

如您所知,每个项目都必须具有唯一的地址。 我建议地址越短越容易对所涉及的每个人 – 您的路由代码,客户端应用程序等等。如果您可以通过其唯一ID识别Bar,我可能只会在URL中指定。

但是,您不需要丢失有关Bar对Foo的赋值的语义信息。 这可能是代表性的一部分。

作为增强function,您可以允许客户端将Bar 200作为/ foo / 100 / bar / 200进行寻址,然后使用例如303(“See Other”)响应重定向到首选/ bar / 200 /地址。

Rails的浅层嵌套为我们提供了两全其美的优势:它让我们拥有特定于Foo的路径(创建,新建,索引)和仅限Bar的路径(显示,编辑,更新,销毁)。

不幸的是,Rails 3中的新路由DSL(我正在使用) 还不支持浅路由(从Beta 3开始)。 它似乎在起作用,但它今天不起作用。

但是,您可以通过将资源映射两次,嵌套一次并浅填一次来伪造它:

 resources :foo do resources :bar, :only => [:index, :new, :create] end resources :bar, :only => [:show, :edit, :update, :destroy] 

这将让我感到震惊,直到:浅层选项再次启动并运行。

就个人而言,如果每个Bar都依赖于Foo,则选项#2更有意义。 例如,如果Foo是博客而Bar是post,那么访问example.bloghosting.com/blog/1/post/2的特定post比使用example.bloghosting.com/post/21更合乎逻辑。

使用最新版本的Rails执行此操作:

 class Food < ActiveRecord::Base has_many :bars end class Bar < ActiveRecord::Base belongs_to :foo end 

然后,在Rails路由器(/config/routes.rb)中:

 map.resources :foos do |foo| foo.resource :bars end 

有关更多信息,请参阅Outside In和Rails API文档中的 Rails路由 。