Ruby - 忽略受保护的属性

时间:2013-02-21 17:44:10

标签: ruby-on-rails ruby rails-activerecord

如何告诉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属性。如果我尝试对其进行大量分配,请忽略它。

5 个答案:

答案 0 :(得分: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

答案 1 :(得分:2)

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

config.active_record.mass_assignment_sanitizer = :logger

答案 2 :(得分:1)

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

请参阅文档here

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

答案 3 :(得分:0)

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

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

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

答案 4 :(得分: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!">