29

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)这个问题,这是允许所有嵌套属性

+0

尝试读取这个答案可能是,这是有帮助的。 > http://stackoverflow.com/questions/14483963/rails-4-0-strong-parameters-nested-attributes-with-a-key-that-points-to-a-hash –

+0

谢谢,但我看到这个。如果您注意到它正在进行与传递文件名相关的选择性属性过滤('assets_attributes :: filename')的相同操作。我想允许嵌套属性的所有参数 – AnkitG

回答

10

的强烈参数的整点是它的名字:让你的输入参数强大。
允许所有参数将是一个非常糟糕的主意,因为它允许任何人插入不需要用户更新的值。

在你给出的例子中,你提到了你目前需要提供的两个参数:
[:lever_id, :explanation]

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

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

编辑:对于人们downvoting这一点。这可能不是你正在寻找的答案,但它是你需要的答案。
将所有嵌套属性列入白名单是一个巨大的安全缺陷,强大的参数试图保护您,并且您将其删除。书写时https://gist.github.com/peternixey/1978249

+1

谢谢,你的回答是一个有效的观点,它可能是一个安全问题。我会明确提及这些属性。 – AnkitG

+17

如果您收到的散列存储在序列化的JSON列中,那么对于这些​​密钥不存在安全问题。 (除了现有的关于太大输入的担忧)。我有这个用例,我想允许散列中的任意键。 –

+2

还有其他一些保护属性的方法。例如,抛弃不允许的参数的命令对象是一种更好的方法,恕我直言。 – karmajunkie

46

我所遇到的其中一个嵌套PARAMS散列允许的任意键的唯一情况似乎合理的,我的是:
看看什么导致建筑strong_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关键的礼物。

+0

非常感谢,您节省了我很多时间:) –

+1

这是正确的答案!你应该得到一个绿色的复选框! –

+2

为什么'params.require(:post).fetch(:options,nil)'而不是'params.require(:post)[:options]'? –

5

尝试

params.require(:lever).permit(:name, leave_benefit_attributes: LeaveBenefit.attribute_names.collect { |att| att.to_sym }) 
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警告/错误。

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) 

不要。


来源:

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

+2

这不适用于Rails 5中的深层嵌套参数。请参阅这里的原因:http://eileencodes.com/posts/actioncontroller-parameters-now-returns-an-object-instead-of-a-hash/ – rmcsharry