Rails:获取嵌套资源的父对象

时间:2013-02-19 13:57:11

标签: ruby-on-rails nested-resources

我有一个属于许多不同模型的嵌套资源。例如:

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 . . . .

我有几十个模型,我必须以这种方式分支,这似乎很草率。是否有更好的(可能是烘焙的)方法,我不考虑?

3 个答案:

答案 0 :(得分:13)

我这样做的方法是将父模型类名添加为路径中的默认参数。

对于问题示例,这应该是:

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])

答案 1 :(得分:11)

不是真正的解决方案,但你可以逃脱

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

如果您在参数名称和模型之间使用约定

答案 2 :(得分:1)

作为已接受答案的替代方案,您可以使用这样的动态路线:

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

这应该允许您在historyies_controller.rb中访问类似的父类

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

如果需要,您也可以在路线中的item_controller上添加约束。