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 и не хочу повторять это в каждой связанной «родительской» модели (потому что это утомительно и очень подвержено глупым ошибкам, таким как пропуск одного атрибута в одна из нескольких родительских моделей).


person mrong    schedule 21.05.2014    source источник
comment
Что вы имеете в виду под вложенной моделью?   -  person mdesantis    schedule 21.05.2014
comment
У меня есть одна родительская модель, которая принимает атрибуты для другой модели (вложенной модели). Возможно, вложенный ресурс — лучший термин?   -  person mrong    schedule 21.05.2014
comment
Ох, хорошо; Я думаю, что лучше связанная модель или связанная запись   -  person mdesantis    schedule 21.05.2014
comment
Хорошо, я изменил его на связанную модель, надеюсь, это прояснит сценарий.   -  person mrong    schedule 21.05.2014


Ответы (2)


Используйте метод, определенный внутри ApplicationController, или общий модуль:

  1. 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
    
  2. Общий модуль:

    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

person mdesantis    schedule 21.05.2014
comment
это намного (му-у-у) лучше, спасибо. До сих пор не знал о проблемах. Сейчас я использую проблему для вложенных разрешений, поэтому я могу один раз определить атрибуты из белого списка и использовать их в определенных родительских контроллерах. Извините, я не имею права голосовать, поэтому неофициально +100 с моей стороны - person mrong; 21.05.2014
comment
Рад помочь; Я предлагаю вам узнать больше о ActiveSupport::Concern; Я не связал его в ответе, потому что для ваших нужд общего модуля действительно достаточно, но он полезен для более сложных сценариев с общими функциями. - person mdesantis; 21.05.2014

Я не понимаю, почему бы и нет. В вашем 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

Затем в вашейorganization_params

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
person SteveTurczyn    schedule 21.05.2014