【问题标题】:strong parameters permit all attributes for nested attributes强参数允许嵌套属性的所有属性
【发布时间】:2013-07-22 13:28:02
【问题描述】:

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) 混淆,这是为了允许所有嵌套属性

【问题讨论】:

  • 尝试阅读此答案可能会有所帮助。 > stackoverflow.com/questions/14483963/…
  • 谢谢,但我已经看到了。如果您注意到它正在做与传递文件名的选择性属性过滤(assets_attributes: :filename)相同的事情。我想允许嵌套属性的所有参数

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


【解决方案1】:

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

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 密钥的礼物。

【讨论】:

  • 非常感谢,您节省了我很多时间:)
  • 这是正确答案!你应该得到一个绿色的复选框!
  • 为什么是params.require(:post).fetch(:options, nil) 而不是params.require(:post)[:options]
  • @PatrickBrinich-Langlois 也不记得fetch 是从哪里来的。更新了答案。
【解决方案2】:

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

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)

不要。


来源:

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

【讨论】:

【解决方案3】:

首先,确保您确实希望允许嵌套散列中的所有值。通读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 警告/错误。

【讨论】:

    【解决方案4】:

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

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

    【讨论】:

    • 它允许lever_benefit_attributes 中散列中的任何属性。为我工作,
    • 三个小时和许多头痛之后,我也很惊讶。非常适合我在 devise_parameter_sanitizer 中的 jsonb 列。
    【解决方案5】:

    试试

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

    【讨论】:

      【解决方案6】:

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

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

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

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

      编辑:对于对此投反对票的人。这可能不是您要寻找的答案,但却是您需要的答案。
      将所有嵌套属性列入白名单是一个巨大的安全漏洞,强参数试图用它来保护您,而您正在将其删除。
      看看导致构建 strong_params 的原因,以及不使用它对您的不利影响:https://gist.github.com/peternixey/1978249

      【讨论】:

      • 谢谢,您的回答是一个有效的观点,它可能是一个安全问题。我将明确提及属性。
      • 如果您收到的哈希存储在序列化的 JSON 列中,则密钥没有安全问题。 (除了现有的对输入过大的担忧)。我有这个用例,我想允许哈希中的任意键。
      • 还有其他保护属性的方法。例如,抛出未经允许的参数的命令对象是一种更好的方法,恕我直言。
      • 在一些合法的用例中,您希望允许临时参数,例如具有松散或不存在模式的序列化对象。这确实比 never 更频繁地发生
      • 这是一个糟糕的答案。 SO 是为了解决问题,而不是告诉人们他们做错了什么。根据我的说法,这些类型的答案只有在包含作者可能试图做的事情的替代解决方案时才应被视为有效。就像例如请参阅下面的答案。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-12-11
      • 2013-04-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-03
      • 2016-02-06
      • 1970-01-01
      相关资源
      最近更新 更多