2013-02-19 50 views
14

我有一個屬於許多不同模型的嵌套資源。例如:Rails:獲取嵌套資源的父對象

resources :users do 
    resources :histories, only: [:show] 
end 

resources :publications do 
    resources :histories, only: [:show] 
end 

resources :events do 
    resources :histories, only: [:show] 
end 

HistoriesController,我想找到父對象,但我有一個乾燥的方法來處理這個麻煩的想法。此刻,我可以拿出最好的是:

if params[:user_id].present? 
    @parent = User.find(params[:user_id]) 
elsif params[:publication_id].present? 
    @parent = Publication.find(params[:publication_id]) 
elsif . . . . 

我有字面上幾十種型號我通過這種方式,這似乎草率分支。有沒有更好的(也許是烘焙)的方法,我不考慮?

回答

11

不是一個真正的解決方案,但你可以,如果你使用的是參數的名字和你的模型

+0

這會爲我節省很多時間和很多線路。謝謝! – nullnullnull 2013-02-19 14:40:02

1

作爲替代接受的答案之間的約定與

parent_klasses = %w[user publication comment] 
if klass = parent_klasses.detect { |pk| params[:"#{pk}_id"].present? } 
    @parent = klass.camelize.constantize.find params[:"#{klass}_id"] 
end 

跑不掉,你可以使用像這樣的動態路由:

get ':item_controller/:item_id/histories/:id', to: 'histories#show' 

這應該那麼應該允許您訪問父類這樣的事情在你的histories_controller.rb

parent_controller = params[:item_controller] 
parent_class = parent_controller.singularize.camelize.constantize 
@parent = parent_class.find(params[:item_id]) 

如果需要,您也許可以在路由中的item_controller上添加一個約束。

10

我這樣做的方式是添加父模型類名稱作爲路由中的默認參數。

對於問題例如,這應該是這樣的:

resources :users, model_name: 'User' do 
    resources :histories, only: [:show] 
end 

resources :publications, model_name: 'Publication' do 
    resources :histories, only: [:show] 
end 

resources :events, model_name: 'Event' do 
    resources :histories, only: [:show] 
end 

這將在params哈希表中添加型號名稱。

然後在控制器/動作就可以得到像你的父母型號:

params[:model_name].constantize # Gives you the model Class (eg. User) 

和外鍵,如:

params[:model_name].foreign_key # Gives you column name (eg. user_id) 

所以,你可以這樣做:

parent_class = params[:model_name].constantize 
parent_foreing_key = params[:model_name].foreign_key 

parent_object = parent_class.find(params[parent_foreing_key]) 
+2

這是很好,最乾淨的答案IMO – niborg 2016-10-06 20:48:32

+0

這是一個不錯的解決方案,但是當使用它時,我遇到了我的控制器規格問題。我沒有找到現有的Rails方法來爲整個控制器規範設置'model_name'參數的值,所以我必須在每個spec方法中傳遞一個值。 – Matt 2017-10-25 14:05:03