16

多くの異なるモデルに属するネストされたリソースがあります。例えば:

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

私は文字通り何十ものモデルをこのように分岐させなければなりませんが、それはずさんなようです。私が検討していないより良い(おそらく焼き付けられた)アプローチはありますか?

4

3 に答える 3

16

これを行う方法は、ルートのデフォルトパラメータとして親モデルクラス名を追加することです。

質問の例では、これは次のようになります。

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])
于 2015-09-03T09:17:29.053 に答える
13

実際には解決策ではありませんが、あなたは逃げることができます

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

パラメータ名とモデルの間で規則を使用している場合

于 2013-02-19T14:08:46.450 に答える
1

受け入れられた回答の代わりに、次のような動的ルートを使用できます。

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にも制約を追加できる場合があります。

于 2015-06-18T17:25:04.830 に答える