Rails命名空间与嵌套资源

And*_*rew 16 routes namespaces ruby-on-rails nested-resources ruby-on-rails-3

假设我的应用程序有两个型号,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
Run Code Online (Sandbox Code Playgroud)

然而,作为酒吧的一部分的Foos有点特别,与常规的Foos不同.所以,例如,如果我加载foos/1或者bars/1/foos/1,我会看同样的Foo,但我在每种情况下都专注于不同的信息.

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

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

namespace "bar" do
  resources :foos
end
Run Code Online (Sandbox Code Playgroud)

如果我这样做,我可以在第二FoosControllerapp/bar/,并且FoosController可以处理一个酒吧里面的Foos与好的帮助,bar_foo_path(:id)而不是bar_bar_foo_path(:id).

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

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

谢谢!

cle*_*nsp 38

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

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

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

resources :foos
resources :bars do
  resources :foos, :controller => 'bars/foos'
end
Run Code Online (Sandbox Code Playgroud)

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

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

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

@foos = @bar.foos
Run Code Online (Sandbox Code Playgroud)

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

before_filter :get_client

private
def get_client
  @bar = Bar.find(params[:bar_id])
end
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助.=)

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

routes.rb中:

namespace :admin do
  resources :foos
end
Run Code Online (Sandbox Code Playgroud)

我创建了我的控制器:

rails g controller admin/foos
Run Code Online (Sandbox Code Playgroud)

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

  • 在你的情况下,因为bar和foo都是资源,而foo属于bar,所以使用嵌套资源是完全合理的.扩展上面的命名空间解释:如果你处理不同上下文的不同行为,即如果我是管理员,我做A,否则我做B,逻辑是除了最简单或分散,然后我将考虑命名空间并添加一个控制器,以允许我在特定的上下文中工作.在这种情况下,'admin'表示上下文而不是资源. (3认同)

小智 5

这种方法有利.

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

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

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

现在使用时不会出现异常:

Foo::CONST_NAME
Run Code Online (Sandbox Code Playgroud)

要么

Bar::Foo::CONST_NAME
Run Code Online (Sandbox Code Playgroud)