Rails命名空间与嵌套资源

假设我的应用程序有两个型号,Foo和Bar。

Foo可选择belongs_to Bar。

现在我可以查看单个Foo,或者搜索特定的Foo,而FoosController可以处理所有这些。 我的URL就像: foos/1foos/new

有时我想看一个酒吧。 BarsController处理它,我得到它: bars/1bars/1/edit

如果我正在看一个酒吧,我可能想浏览那个酒吧的所有Foos。 所以,我想使用bars/1/foos/来看看那些Foos。

嵌套资源非常简单,它看起来像这样:

 resources :foo resources :bar do resources :foo end 

然而,作为酒吧的一部分的Foos有点特别,与常规的Foos不同。 所以,举例来说,如果我加载foos/1bars/1/foos/1 ,我会看同样的Foo,但我会关注每种情况下的不同信息。

因此,我一直在考虑使用BarFoos控制器来处理Foos,因为它们处于Bar的环境中。 但是,如果我将BarFoos嵌套在Bar下,那么我的助手就像bar_bar_foos_pathnew_bar_bar_foo_path 。 这似乎是多余的。

所以,现在我正在考虑命名空间,这是我以前从未研究过的。 我在rails指南中看到我可以定义:

 namespace "bar" do resources :foos end 

如果我这样做,我可以在app/bar/下创建第二个FoosController ,并且FoosController可以使用bar_foo_path(:id)而不是bar_bar_foo_path(:id)等好帮手来处理Bar内部的Foos。

但是,如果我这样做,我的BarsController会发生什么? 如果不是resources :bars请求如何被路由到BarsController resources :bars我有namespace "bar"

而且,最后,在我的辅助FoosController中我需要做些什么特别的事情来确保与顶级FoosController没有名称冲突? 我意识到路由说“命名空间”,但其余的ruby代码如何知道app/bar/foos_controllerapp/foos_controller不是同一个类?

谢谢!

我想你想要达到的目标是:

  1. 酒吧有很多Foos
  2. 查看属于Bar的Foos
  3. 查看所有Foos,无论父母。

您可以使用:routes.rb实现:

 resources :foos resources :bars do resources :foos, :controller => 'bars/foos' end 

你最终得到的路线助手是:

  • bars_path
  • foos_path
  • bars_foos_path
  • 等等,其余的“耙路线”=)

从本质上讲,你最终得到:

  • app / BarsController(rails g控制器栏)
  • app / FoosController(rails g controller foos)
  • app / bars / FoosController(rails g控制器栏/ foos)

在FoosController中,您可以像往常一样访问foos:

 @foos = Foos.all 

在酒吧/ FoosController中,您可以访问酒吧的foos:

 @foos = @bar.foos 

其中bar可以在bars / foos控制器中预先检索:

 before_filter :get_client private def get_client @bar = Bar.find(params[:bar_id]) end 

希望这可以帮助。 =)

编辑 :对于命名空间路由,当我从子路径检索到一些资源时,我个人使用它们。 例如,如果我有我的网站的管理部分,那么我可能有以下内容:

routes.rb中:

 namespace :admin do resources :foos end 

我创建了我的控制器:

 rails g controller admin/foos 

这会设置我的foos资源,这样我就可以在“my site url”/ admin / foos中访问它,并且还可以获得诸如admin_foos_path之类的帮助程序。

这种方法有利。

如果你声明一个常数,例如。 CONST_NAME,在嵌套资源中,rails会因为其范围算法而抛出“未初始化的常量:: Foo :: CONST_NAME”exception。

要避免此类行为,请使用:

 resources :foos resources :bars do scope :module => "bar" do resources :foos #, :controller => 'bar/foos' no need to use this now because route will be searched there by default end end 

现在使用时不会出现exception:

 Foo::CONST_NAME 

要么

 Bar::Foo::CONST_NAME