Rails命名空间与嵌套资源

时间:2011-03-01 20:35:09

标签: ruby-on-rails ruby-on-rails-3 namespaces routes nested-resources

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

Foo可选择belongs_to Bar。

现在我可以查看单个Foo,或者搜索特定的Foo,而FoosController可以处理所有这些。我的网址如下: 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

如果我这样做,我可以在FoosController下制作第二个app/bar/,并且FoosController可以使用bar_foo_path(:id)而不是bar_bar_foo_path(:id)等好帮手处理条形图中的Foos

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

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

谢谢!

2 个答案:

答案 0 :(得分:38)

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

  1. Bar有很多Foos
  2. 查看属于Bar的Foos
  3. 查看所有Foos,无论是父母。
  4. 您可以通过以下方式实现: 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 controller bars / foos)

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

    @foos = Foos.all
    

    并在bars / FoosController中,您可以访问bar的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之类的帮助。

答案 1 :(得分: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