Rails命名空间与嵌套资源
假设我的应用程序有两个型号,Foo和Bar。
Foo可选择belongs_to Bar。
现在我可以查看单个Foo,或者搜索特定的Foo,而FoosController可以处理所有这些。 我的URL就像: foos/1
和foos/new
有时我想看一个酒吧。 BarsController处理它,我得到它: bars/1
或bars/1/edit
。
如果我正在看一个酒吧,我可能想浏览那个酒吧的所有Foos。 所以,我想使用bars/1/foos/
来看看那些Foos。
嵌套资源非常简单,它看起来像这样:
resources :foo resources :bar do resources :foo end
然而,作为酒吧的一部分的Foos有点特别,与常规的Foos不同。 所以,举例来说,如果我加载foos/1
或bars/1/foos/1
,我会看同样的Foo,但我会关注每种情况下的不同信息。
因此,我一直在考虑使用BarFoos控制器来处理Foos,因为它们处于Bar的环境中。 但是,如果我将BarFoos嵌套在Bar下,那么我的助手就像bar_bar_foos_path
和new_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_controller
和app/foos_controller
不是同一个类?
谢谢!
我想你想要达到的目标是:
- 酒吧有很多Foos
- 查看属于Bar的Foos
- 查看所有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