Rails 4 сильных параметра получают разрешение от вложенной модели
Есть несколько вопросов для сильных параметров, но я не смог найти ответа для достижения своей цели. Пожалуйста, извините за любые дубликаты (и, возможно, укажите мне в правильном направлении). Я использую сильные параметры в модели, которая имеет несколько ассоциаций has_one и вложенные атрибуты с accepts_attributes_for.
В моих маршрутах у меня есть: (обновлено для лучшего понимания)
resources :organisations do
resources :contact_details
end
То есть, для одной связанной модели я должен использовать
def organisation_params
params.require(:organisation).permit(:org_reference, :supplier_reference, :org_type, :name, :org_members, :business, :contact_person, contact_detail_attributes: [:id, :contactable_id, :contactable_type, :phone, :fax, :mail, :state, :province, :zip_code, :street, :po_box, :salutation, :title, :last_name, :first_name, :description])
end
Это работает, но я должен перепечатать все мои разрешенные параметры для каждой связанной модели. Когда я изменяю свои разрешенные атрибуты для contact_details, я должен изменить его в нескольких местах (каждая модель, имеющая полиморфную ассоциацию).
Есть ли способ получить белый список параметров contact_details и включить его в родительский белый список?
Что-то вроде:
def organisation_params
my_params = [:org_reference, :supplier_reference, :org_type, :name, :org_members, :business, :contact_person]
contact_params = #get permitted params, that are defined in contact_details_controller
params.require(:organisation).permit(my_params, contact_params)
end
Я не хочу обойти защиту, но я уже определил разрешенные атрибуты для contact_details и не хочу повторять это в каждой связанной "родительской" модели (потому что это утомительно и очень склонно к глупым ошибкам, таким как пропуск одного атрибута в одна из нескольких родительских моделей).
2 ответа
Используйте метод, определенный внутри ApplicationController
или общий модуль:
ApplicationController
:class ApplicationController def contact_details_permitted_attributes [:id, :contactable_id, :contactable_type, ...] end end class ContactDetailsController < ApplicationController def contact_details_params params .require(contact_details) .permit(*contact_details_permitted_attributes) end end class OrganisationsController < ApplicationController def organisation_params params .require(:organisation) .permit(:org_reference, ..., contact_detail_attributes: contact_details_permitted_attributes) end end
Общий модуль:
module ContactDetailsPermittedAttributes def contact_details_permitted_attributes [:id, :contactable_id, :contactable_type, ...] end end class ContactDetailsController < ApplicationController include ContactDetailsPermittedAttributes def contact_details_params params .require(contact_details) .permit(*contact_details_permitted_attributes) end end class OrganisationsController < ApplicationController include ContactDetailsPermittedAttributes def organisation_params params .require(:organisation) .permit(:org_reference, ..., contact_detail_attributes: contact_details_permitted_attributes) end end
В Rails есть даже специальные каталоги для общих модулей, concerns
внутри app/controllers
а также app/models
; действительно, в вашем случае вы должны использовать app/controllers/concerns
Я не понимаю, почему нет. В вашем ApplicationController вы могли бы иметь
def contact_attributes
[:id, :contactable_id, :contactable_type, :phone, :fax,
:mail, :state, :province, :zip_code, :street, :po_box,
:salutation, :title, :last_name, :first_name, :description]
end
Тогда в вашей организации_парамс
def organisation_params
my_params = [:org_reference, :supplier_reference, :org_type, :name, :org_members, :business, :contact_person]
params.require(:organisation).permit(*my_params, contact_detail_attributes: contact_attributes)
end
В другом месте вы можете сделать...
def contact_params
params.require(:contact).permit(*contact_attributes)
end