【问题标题】:Rails 4 strong params get permit from nested modelRails 4强参数从嵌套模型中获得许可
【发布时间】:2014-05-21 16:45:13
【问题描述】:

强参数有几个问题,但我找不到任何答案来实现我的目标。请原谅任何重复(也许指出我正确的方向)。 我在具有多个“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 定义了允许的属性,并且不想在每个关联的“父”模型中重复它(因为它很累而且很容易出现愚蠢的错误,比如省略几个父模型之一中的一个属性)。

【问题讨论】:

  • “嵌套模型”是什么意思?
  • 我有一个“父”模型,它接受另一个模型(“嵌套模型”)的属性。也许嵌套资源是一个更好的术语?
  • 哦,好的;我认为“关联模型”或“关联记录”更好
  • 好的,我把它改成关联模型,希望它能澄清场景

标签: ruby-on-rails ruby ruby-on-rails-4 strong-parameters


【解决方案1】:

使用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 甚至有共享模块的专用目录,concernsapp/controllersapp/models 中;事实上,在你的情况下,你应该使用app/controllers/concerns

【讨论】:

  • 这好多了(muuuch),谢谢。到目前为止还不知道关注点。我现在正在使用对嵌套权限的关注点,因此我可以定义一次列入白名单的属性并在特定的“父”控制器中使用它们。抱歉,我没有资格投票,所以非官方 +100 从我这边
  • 很高兴为您提供帮助;建议大家多了解ActiveSupport::Concern;我没有在答案中链接它,因为对于您的需要,共享模块确实足够了,但它对于更复杂的共享功能场景很有用
【解决方案2】:

我不明白为什么不。在您的 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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-07-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多