14

假設我的應用程序有兩個模型,Foo和Bar。Rails命名空間與嵌套資源

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,當他們在一個酒吧的上下文中。但是,如果我將BarFoos嵌入Bar中,那麼我的助手將會像bar_bar_foos_pathnew_bar_bar_foo_path一樣。這似乎是多餘的。

所以,現在我正在考慮命名空間,這是我以前從未考慮過的。我看到在鐵軌指南,我可以定義:

namespace "bar" do 
    resources :foos 
end 

如果我這樣做,我可以做一個第二FoosControllerapp/bar/下,這FoosController可以處理FOOS一個酒吧內與漂亮的助手像bar_foo_path(:id),而不是bar_bar_foo_path(:id)

但是,如果我這樣做,我的BarsController會發生什麼?如果請求被路由到BarsController而不是resources :bars我有namespace "bar"

最後,在我的第二個FoosController裏面有什麼特別的要做,以確保沒有與頂層FoosController的名稱衝突?我意識到路由說「命名空間」,但其餘的紅寶石代碼如何知道app/bar/foos_controllerapp/foos_controller不是同一類?

謝謝!

回答

36

我想你想達到什麼是:

  1. 酒吧有很多FOOS
  2. 查看FOOS屬於酒吧
  3. 查看所有FOOS考慮父。

您可以通過以下方式實現: 路線。RB:

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

你最終的路線助手是:

  • bars_path
  • foos_path
  • bars_foos_path
  • 等,等, '耙路線' 的其餘 =)

從本質上講,你最終:

  • 應用程序/ BarsController(軌道克控制器柱)
  • 應用程序/ FoosController(軌道克控制器FOOS)
  • 應用程序/棒/ FoosController(軌道克控制器條/ FOOS)

在FoosController,你將訪問FOOS像往常一樣:

@foos = Foos.all 

,並在酒吧/ FoosController,你會進入酒吧的FOOS用:

@foos = @bar.foos 

其中杆可在杆/ 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資源,以便我可以在「我的站點URL」/ admin/foos中訪問它,並且還可以獲得助理,如admin_foos_path。

+0

你是我的方案的描述是完全正確,而你的回答非常清楚,謝謝!我明白你的答案會如何工作,所以這太棒了!只是爲了跟進一個細節,你會推薦*在這種情況下嵌套命名空間?你能否提供你經歷過的任何優點/缺點? – Andrew 2011-03-02 00:35:34

+3

就你而言,因爲bar和foo都是資源,而foo屬於bar,所以使用嵌套資源非常合理。爲了擴展上面的命名空間解釋:如果你處於不同情境的不同行爲的情況下,也就是說如果我是管理員,我做A,否則我做B,邏輯是除了最簡單的或分散的,然後我會考慮命名空間並添加一個控制器,以允許我在特定的上下文中工作。 'admin'代表一個上下文而不是這種情況下的資源。 – clemensp 2011-03-02 00:54:53

+0

太棒了,這很有道理! – Andrew 2011-03-04 02:31:52

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