Ruby on rails 强参数允许嵌套属性的所有属性

Ruby on rails 强参数允许嵌套属性的所有属性,ruby-on-rails,ruby,ruby-on-rails-3.2,ruby-on-rails-4,strong-parameters,Ruby On Rails,Ruby,Ruby On Rails 3.2,Ruby On Rails 4,Strong Parameters,中是否有允许嵌套的_属性模型的所有属性的方法?下面是一个示例代码 class Lever < ActiveRecord::Base has_one :lever_benefit accepts_nested_attributes_for :lever_benefit end class LeverBenefit < ActiveRecord::Base # == Schema Information # id :integer no

中是否有允许嵌套的_属性模型的所有属性的方法?下面是一个示例代码

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
是否有一种嵌套属性的方法我可以编写以允许所有属性,而无需明确给出属性名称,如
lever\u id
解释


注意:请不要将此问题与
许可混淆
允许(:all)
这是用于允许嵌套属性的所有属性

强参数的全部要点在于其名称:使您的输入参数变强。
def lever
 params.require(:lever).permit(:name,:lever_benefit_attributes => [:lever_id, :explanation])
end
允许所有参数将是一个非常糟糕的主意,因为这将允许任何人插入您不一定希望用户更新的值

在您给出的示例中,您提到了当前需要提供的两个参数:
[:杠杆id,:解释]

如果您允许所有参数,则有人可以更改任何其他值。
例如,在处创建的,或杠杆id

这肯定是一个安全问题,这就是您不应该这样做的原因。
明确指定所有属性可能会让您觉得很无聊。
但这对于保持应用程序的安全是必要的

编辑:用于投票否决此项的人。这可能不是您想要的答案,但却是您需要的答案。
将所有嵌套属性列入白名单是一个巨大的安全缺陷,强参数试图用它来保护您,您正在删除它。

看看是什么导致构建强参数,以及不使用强参数会对您造成什么样的危害:

我遇到的唯一一种情况是,在嵌套参数散列中允许任意键对我来说是合理的,那就是写入序列化列时。我已经设法这样处理了:

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
class Post
序列化:选项,JSON
结束
类PostsController<应用程序控制器
...
def post_参数
all_options=params.require(:post)[:options]。try(:permit!)
参数require(:post).permit(:title).merge(:options=>all_options)
结束
结束
try
确保我们不需要提供
:选项
键。

试试看

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

首先,确保您确实希望允许嵌套哈希中的所有值。通读以了解可能打开的安全漏洞

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

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

注意:这非常类似于但有点优雅,因为您不会得到任何未经许可的参数:lever\u benefit\u属性警告/错误。

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

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)
不要


资料来源:


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

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

谢谢,你的回答是正确的,它可能是一个安全问题。我将明确提到属性。如果您接收的哈希存储在序列化的JSON列中,那么密钥就没有安全问题。(除了投入过大的现有问题)。我有这个用例,我希望允许散列中的任意键。还有其他保护属性的方法。例如,抛出未经许可的参数的命令对象是一种更好的方法,IMHO。在一些合法的用例中,您可能希望允许使用临时参数,例如带有松散或不存在模式的序列化对象。这种情况确实经常发生——这是一个糟糕的答案。解决问题也是如此,不告诉人们他们所做的是错的。在我看来,这些类型的答案只有在包含了作者可能试图做的事情的替代解决方案时才被视为有效。例如,参考下面的答案。尝试阅读此答案可能会有所帮助。>谢谢,不过我已经看过了。如果您注意到它正在执行与传递文件名相同的选择性属性过滤(
assets\u attributes::filename
)操作。我想允许嵌套属性的所有参数谢谢你,你节省了我很多时间:)这是正确的答案!你应该得到一个绿色的复选框!为什么
params.require(:post).fetch(:options,nil)
而不是
params.require(:post)[:options]
?@PatrickBrinich Langlois也记不起
fetch
的来源。更新了答案。这不适用于Rails 5中的深度嵌套参数。请参见此处的原因:它允许
lever\u benefit\u attributes
中哈希中的任何属性。对我来说很有效,三个小时后又头痛不已,我也很惊讶。非常适合我在Desive_parameter_Sanitarizer中的jsonb专栏。