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