strong参数允许嵌套属性的所有属性

时间:2013-07-23 12:57:20

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

strong parameters中是否有办法允许 nested_attributes模型的所有属性?这是一个示例代码。

class Lever < ActiveRecord::Base
 has_one :lever_benefit
 accepts_nested_attributes_for :lever_benefit
end

class LeverBenefit < ActiveRecord::Base
  # == Schema Information
  #  id          :integer          not null, primary key
  #  lever_id    :integer
  #  explanation :text
end

对于目前正在撰写的杠杆强参数

def lever
 params.require(:lever).permit(:name,:lever_benefit_attributes => [:lever_id, :explanation])
end

是否有办法嵌套属性我可以编写以允许所有属性而不显式提供属性名称lever_idexplanation

注意:请不要将此问题与permit!permit(:all)混淆,这是针对允许所有嵌套属性

6 个答案:

答案 0 :(得分:52)

我遇到的唯一情况是允许嵌套params散列中的任意键对我来说似乎是合理的,当写入序列化列时。我设法像这样处理它:

class Post
  serialize :options, JSON
end

class PostsController < ApplicationController
  ...

  def post_params
    all_options = params.require(:post)[:options].try(:permit!)
    params.require(:post).permit(:title).merge(:options => all_options)
  end
end

try确保我们不需要:options密钥的提示。

答案 1 :(得分:15)

实际上有一种方法可以将所有嵌套参数列入白名单。

params.require(:lever).permit(:name).tap do |whitelisted|
  whitelisted[:lever_benefit_attributes ] = params[:lever][:lever_benefit_attributes ]
end

此方法优于其他解决方案。 允许深层嵌套参数。

其他解决方案如:

nested_keys = params.require(:lever).fetch(:lever_benefit_attributes, {}).keys
params.require(:lever).permit(:name,:lever_benefit_attributes => nested_keys)

唐&#39;吨


来源:

https://github.com/rails/rails/issues/9454#issuecomment-14167664

答案 2 :(得分:10)

首先,确保您确实希望允许嵌套哈希中的所有值。仔细阅读Damien MATHIEU's answer以了解安全漏洞的可能开放......

如果您仍然需要/希望允许散列中的所有值(对于此有完全有效的用例,例如存储记录的非结构化,用户提供的元数据),您可以使用以下代码来实现它:

def lever_params
  nested_keys = params.require(:lever).fetch(:lever_benefit_attributes, {}).keys
  params.require(:lever).permit(:name,:lever_benefit_attributes => nested_keys)
end

注意:这与tf.'s answer非常相似,但更优雅,因为您不会收到任何Unpermitted parameters: lever_benefit_attributes警告/错误。

答案 3 :(得分:6)

params.require(:lever).permit(:name, leave_benefit_attributes: LeaveBenefit.attribute_names.collect { |att| att.to_sym })

答案 4 :(得分:4)

我很惊讶没有人提出这样的建议:

params.require(:lever).permit(:name,:lever_benefit_attributes => {})

答案 5 :(得分:1)

强参数的重点在于其名称:使您的输入参数更强 允许所有参数将是一个非常糟糕的主意,因为它允许任何人插入您不一定希望由用户更新的值。

在您给出的示例中,您提到了您当前需要提供的两个参数:
[:lever_id, :explanation]

如果您允许所有参数,则某人可能会更改任何其他值 例如created_atlever_id

这肯定是一个安全问题,这就是你不应该这样做的原因 当你这样做时,明确指定你的所有属性可能看起来很无聊 但这对于确保您的应用程序安全是必要的。

修改:对于那些贬低此事的人。这可能不是您正在寻找的答案,但它是您需要的答案 将所有嵌套属性列入白名单是一个巨大的安全漏洞,强大的params试图保护您,并且您将其删除。
看一下构建strong_params的原因,以及如何不使用它对您有害:https://gist.github.com/peternixey/1978249