Rails: получение родительского объекта вложенного ресурса - программирование
Подтвердить что ты не робот

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

У меня есть буквально десятки моделей, которые мне приходится прокладывать таким образом, что кажется неаккуратным. Есть ли лучший (возможно, запеченный) подход, который я не рассматриваю?

4b9b3361

Ответ 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

если вы используете соглашение между вашим именем параметра и вашими моделями

Ответ 2

Я делаю это, добавляя имя класса родительской модели в качестве параметра по умолчанию в маршруте.

Для примера вопроса это должно выглядеть примерно так:

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

Ответ 3

В качестве альтернативы принятому ответу вы можете использовать динамический маршрут следующим образом:

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 на маршрутах, если вам нужно.