1

如何告诉 Ruby (Rails) 忽略批量分配时存在的受保护变量?

class MyClass < ActiveRecord::Base
    attr_accessible :name, :age
end

现在我将批量分配一个哈希来创建一个新的MyClass.

MyClass.create!({:name => "John", :age => 25, :id => 2})

这会给我一个例外:

ActiveModel::MassAssignmentSecurity::Error: Can't mass-assign protected attributes: id

我希望它创建一个MyClass具有指定(不受保护)属性的新属性并忽略该id属性。

旁注:我如何也忽略未知属性。例如,MyClass没有location属性。如果我尝试批量分配它,请忽略它。

4

5 回答 5

5

用于Hash#slice仅选择您真正有兴趣分配的键:

# Pass only :name and :age to create!
MyClass.create!(params.slice(:name, :age))

通常,我会为我的控制器添加包装器方法,params将其过滤到仅我知道我想要分配的字段:

class MyController

  # ...

  def create
    @my_instance = MyClass.create!(create_params)
  end

protected

  def create_params
    params.slice(:name, :age)
  end
end
于 2013-02-21T17:46:54.047 回答
3

设置mass_assignment_sanitizer:logger解决开发和测试中的问题。

config.active_record.mass_assignment_sanitizer = :logger
于 2013-02-21T18:38:54.207 回答
1

您可以使用 strong_parameters gem,它将在 rails 4 中。

请参阅此处的文档。

例如,通过这种方式,您可以通过操作或角色指定所需的参数。

于 2013-02-21T18:37:30.187 回答
0

如果你想对它下手,并动态地只让模型的属性通过,而不全局禁用 ActiveModel::MassAssignmentSecurity::Errors:

params = {:name => "John", :age => 25, :id => 2}
MyClass.create!(params.slice(*MyClass.new.attributes.symbolize_keys.keys)

如果您在哈希中使用符号,则需要 .symbolize_keys,就像在这种情况下一样,但您可能不需要。

于 2013-05-09T13:48:32.760 回答
0

就个人而言,我喜欢通过覆盖将东西保留在模型中assign_attributes

def assign_attributes(new_attributes, options = {})
  if options[:safe_assign]
    authorizer = mass_assignment_authorizer(options[:as])
    new_attributes = new_attributes.reject { |key|
      !has_attribute?(key) || authorizer.deny?(key)
    }
  end
  super(new_attributes, options)
end

与 类似地使用它:without_protection,但是当您想忽略未知或受保护的属性时:

MyModel.create!(
  { :asdf => "invalid", :admin_field => "protected", :actual_data => 'hello world!' },
  :safe_assign => true
)
# => #<MyModel actual_data: "hello world!">
于 2020-03-20T18:37:08.620 回答