I have a nested resource that belongs to many different models. For instance:
我有一个嵌套资源,属于许多不同的模型。例如:
resources :users do
resources :histories, only: [:show]
end
resources :publications do
resources :histories, only: [:show]
end
resources :events do
resources :histories, only: [:show]
end
In the HistoriesController
, I want to find the parent object, though I'm having trouble thinking of a dry way to handle this. At the moment, the best I can come up with is:
在历史控制器中,我想找到父对象,尽管我想不出一个干巴巴的方法来处理它。目前,我能想到的最好的办法是:
if params[:user_id].present?
@parent = User.find(params[:user_id])
elsif params[:publication_id].present?
@parent = Publication.find(params[:publication_id])
elsif . . . .
I've got literally dozens of models I have to branch through in this way, which seems sloppy. Is there a better (perhaps baked-in) approach that I'm not considering?
我有几十个模型,我必须以这种方式进行分支,这看起来很草率。有没有更好的(可能是烘烤的)方法是我没有考虑的?
3 个解决方案
#1
12
not really a solution but you can get away with
不是一个真正的解决方案,但你可以侥幸过关
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
if you are using a convention between your parameter name and your models
如果在参数名和模型之间使用约定
#2
11
The way I am doing this is adding the parent model class name as a default param in the route.
我这样做的方式是在路径中添加父模型类名作为默认参数。
For the question example this should be something like:
这个问题的例子应该是这样的:
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
This will add the model name in the params hash.
这将在params散列中添加模型名。
Then in the controller/action you can get your parent model like:
然后在控制器/动作中,您可以得到父模型,如:
params[:model_name].constantize # Gives you the model Class (eg. User)
and the foreign key like:
外键是:
params[:model_name].foreign_key # Gives you column name (eg. user_id)
So you can do something like:
你可以这样做:
parent_class = params[:model_name].constantize
parent_foreing_key = params[:model_name].foreign_key
parent_object = parent_class.find(params[parent_foreing_key])
#3
1
As an alternative to the accepted answer, you could use a dynamic route like this:
作为被接受的答案的替代,你可以使用这样的动态路线:
get ':item_controller/:item_id/histories/:id', to: 'histories#show'
This should then should allow you to access the parent class something like this in your histories_controller.rb
然后,这应该允许您访问类似这样的父类
parent_controller = params[:item_controller]
parent_class = parent_controller.singularize.camelize.constantize
@parent = parent_class.find(params[:item_id])
You may be able to add a constraint on item_controller in the routes as well if you need to.
如果需要,还可以在路由中为item_controller添加约束。
#1
12
not really a solution but you can get away with
不是一个真正的解决方案,但你可以侥幸过关
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
if you are using a convention between your parameter name and your models
如果在参数名和模型之间使用约定
#2
11
The way I am doing this is adding the parent model class name as a default param in the route.
我这样做的方式是在路径中添加父模型类名作为默认参数。
For the question example this should be something like:
这个问题的例子应该是这样的:
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
This will add the model name in the params hash.
这将在params散列中添加模型名。
Then in the controller/action you can get your parent model like:
然后在控制器/动作中,您可以得到父模型,如:
params[:model_name].constantize # Gives you the model Class (eg. User)
and the foreign key like:
外键是:
params[:model_name].foreign_key # Gives you column name (eg. user_id)
So you can do something like:
你可以这样做:
parent_class = params[:model_name].constantize
parent_foreing_key = params[:model_name].foreign_key
parent_object = parent_class.find(params[parent_foreing_key])
#3
1
As an alternative to the accepted answer, you could use a dynamic route like this:
作为被接受的答案的替代,你可以使用这样的动态路线:
get ':item_controller/:item_id/histories/:id', to: 'histories#show'
This should then should allow you to access the parent class something like this in your histories_controller.rb
然后,这应该允许您访问类似这样的父类
parent_controller = params[:item_controller]
parent_class = parent_controller.singularize.camelize.constantize
@parent = parent_class.find(params[:item_id])
You may be able to add a constraint on item_controller in the routes as well if you need to.
如果需要,还可以在路由中为item_controller添加约束。