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

Ank*_*itG 30 ruby ruby-on-rails ruby-on-rails-3.2 strong-parameters ruby-on-rails-4

强参数中是否有一种方法可以允许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
Run Code Online (Sandbox Code Playgroud)

对于杠杆强参数,我正在写这个

def lever
 params.require(:lever).permit(:name,:lever_benefit_attributes => [:lever_id, :explanation])
end
Run Code Online (Sandbox Code Playgroud)

有没有办法可以编写嵌套属性来允许所有属性而不显式赋予属性名称lever_idexplanation

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

tfi*_*ach 54

我在嵌套的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
Run Code Online (Sandbox Code Playgroud)

try确保我们不需要:options钥匙的礼物.

  • 这是正确的答案!您值得拥有一个绿色复选框! (2认同)
  • 为什么`params.require(:post).fetch(:options,nil)`而不是`params.require(:post)[:options]`? (2认同)

not*_*ere 15

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

params.require(:lever).permit(:name).tap do |whitelisted|
  whitelisted[:lever_benefit_attributes ] = params[:lever][:lever_benefit_attributes ]
end
Run Code Online (Sandbox Code Playgroud)

该方法优于其他解决方案.它允许允许深层嵌套的参数.

其他解决方案如:

nested_keys = params.require(:lever).fetch(:lever_benefit_attributes, {}).keys
params.require(:lever).permit(:name,:lever_benefit_attributes => nested_keys)
Run Code Online (Sandbox Code Playgroud)

别.


资源:

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

  • 这对于Rails 5中的深层嵌套参数不起作用.请参见http://eileencodes.com/posts/actioncontroller-parameters-now-returns-an-object-instead-of-a-hash/ (3认同)

sev*_*rin 11

首先,确保您确实希望允许嵌套哈希中的所有值.阅读Damien MATHIEU的答案,了解安全漏洞的潜在开放......

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

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

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


小智 8

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

params.require(:lever).permit(:name,:lever_benefit_attributes => {})
Run Code Online (Sandbox Code Playgroud)


seu*_*ner 6

尝试

params.require(:lever).permit(:name, leave_benefit_attributes: LeaveBenefit.attribute_names.collect { |att| att.to_sym })
Run Code Online (Sandbox Code Playgroud)


Dam*_*IEU -4

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

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

如果您允许所有参数,那么其他人就有可能更改任何其他值。
created_at,或者lever_id例如。

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

编辑:对于那些对此投反对票的人。这可能不是您正在寻找的答案,但却是您需要的答案。
将所有嵌套属性列入白名单是一个巨大的安全缺陷,强参数试图用它来保护你,而你正在删除它。
看看是什么导致了构建 Strong_params,以及不使用它会对您造成什么不好: https: //gist.github.com/peternixey/1978249

  • 如果您收到的哈希存储在序列化的 JSON 列中,则密钥不存在安全问题。(除了现有的输入太大的担忧)。我有这个用例,我想允许散列中的任何任意键。 (30认同)
  • 在某些合法的用例中,您可能希望允许使用临时参数,例如具有松散或不存在架构的序列化对象。这种情况发生的频率确实比“从不发生”要高得多 (15认同)
  • 这是一个糟糕的答案。SO是为了解决问题,而不是告诉人们他们所做的事情是错误的。在我看来,只有当这些类型的答案包含了作者可能尝试做的事情的替代解决方案时,才应被视为有效。例如,请参阅下面的答案。 (5认同)
  • 还有其他方法来保护属性。例如,抛出不允许的参数的命令对象是一种更好的方法,恕我直言。 (2认同)