18

假设我的应用有两个模型,Foo 和 Bar。

Foo 可选belongs_to Bar。

现在我可以查看一个 Foo,或者搜索一个特定的 Foo,而 FoosController 会处理所有这些。我的网址是: foos/1foos/new

有时我想看看一个酒吧。BarsController 处理它,我像这样处理它: bars/1bars/1/edit.

如果我正在查看 Bar,我可能想浏览属于该 Bar 的所有 Foos。所以,我想bars/1/foos/用来看看那些Foos。

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

resources :foo
resources :bar do
  resources :foo
end

但是,作为 Bar 一部分的 Foo 有点特殊,与常规 Foo 不同。因此,例如,如果我加载foos/1or bars/1/foos/1,我将查看相同的 Foo,但我在每种情况下都关注不同的信息。

所以我一直在考虑让 BarFoos 控制器在 Bar 的上下文中处理 Foos。但是,如果我将 BarFoos 嵌套在 Bar 下,那么我的助手将类似于bar_bar_foos_pathand new_bar_bar_foo_path。这似乎是多余的。

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

namespace "bar" do
  resources :foos
end

如果我这样做了,我可以FoosController在.app/bar/bar_foo_path(:id)bar_bar_foo_path(:id)

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

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

谢谢!

4

2 回答 2

42

我认为你想要实现的是:

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

您可以通过以下方式实现:routes.rb:

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

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

  • bar_path
  • foos_path
  • bar_foos_path
  • 等等,等等,其余的“耙路线”=)

本质上,您最终会得到:

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

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

@foos = Foos.all

在 bar/FoosController 中,您可以使用以下命令访问 bar 的 foos:

@foos = @bar.foos

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

before_filter :get_client

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

希望这可以帮助。=)

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

路线.rb:

namespace :admin do
  resources :foos
end

我创建了我的控制器:

rails g controller admin/foos

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

于 2011-03-02T00:08:37.053 回答
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

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

Foo::CONST_NAME

或者

Bar::Foo::CONST_NAME
于 2012-07-11T13:00:45.027 回答