是否有不保存记录的 update_attributes
替代方法?
所以我可以做类似的事情:
@car = Car.new(:make => 'GMC')
#other processing
@car.update_attributes(:model => 'Sierra', :year => "2012", :looks => "Super Sexy, wanna make love to it")
#other processing
@car.save
顺便说一句,我知道我可以@car.model = 'Sierra'
,但我想在一行上更新它们。
assign_attributes
apidock.com/rails/ActiveRecord/Base/assign_attributes
我相信您正在寻找的是 assign_attributes
。
它与 update_attributes 基本相同,但不保存记录:
class User < ActiveRecord::Base
attr_accessible :name
attr_accessible :name, :is_admin, :as => :admin
end
user = User.new
user.assign_attributes({ :name => 'Josh', :is_admin => true }) # Raises an ActiveModel::MassAssignmentSecurity::Error
user.assign_attributes({ :name => 'Bob'})
user.name # => "Bob"
user.is_admin? # => false
user.new_record? # => true
您可以使用 assign_attributes
或 attributes=
(它们相同)
更新方法备忘单(适用于 Rails 6):
更新 = 分配属性 + 保存
attributes= = assign_attributes 的别名
update_attributes = 已弃用,更新的别名
来源:
https://github.com/rails/rails/blob/master/activerecord/lib/active_record/persistence.rb
https://github.com/rails/rails/blob/master/activerecord/lib/active_record/attribute_assignment.rb
另一个备忘单:
http://www.davidverhasselt.com/set-attributes-in-activerecord/#cheat-sheet
您可以使用“属性”方法:
@car.attributes = {:model => 'Sierra', :years => '1990', :looks => 'Sexy'}
来源:http://api.rubyonrails.org/classes/ActiveRecord/Base.html
attributes=(new_attributes, guard_protected_attributes = true) 允许您通过传入带有与属性名称匹配的键的哈希(再次与列名称匹配)来一次设置所有属性。
如果guard_protected_attributes 为真(默认值),则可以使用attr_protected 宏保护敏感属性免受这种形式的批量分配。或者,您也可以使用 attr_accessible 宏指定可以访问哪些属性。那么所有未包含在其中的属性将不允许批量分配。
class User < ActiveRecord::Base
attr_protected :is_admin
end
user = User.new
user.attributes = { :username => 'Phusion', :is_admin => true }
user.username # => "Phusion"
user.is_admin? # => false
user.send(:attributes=, { :username => 'Phusion', :is_admin => true }, false)
user.is_admin? # => true
要在不保存的情况下将值批量分配给 ActiveRecord 模型,请使用 assign_attributes
或 attributes=
方法。这些方法在 Rails 3 和更新版本中可用。但是,需要注意一些细微的差异和与版本相关的问题。
两种方法都遵循这种用法:
@user.assign_attributes{ model: "Sierra", year: "2012", looks: "Sexy" }
@user.attributes = { model: "Sierra", year: "2012", looks: "Sexy" }
请注意,这两种方法都不会执行验证或执行回调;调用 save
时将发生回调和验证。
导轨 3
attributes=
与 Rails 3 中的 assign_attributes
略有不同。attributes=
将检查传递给它的参数是否为 Hash,如果不是则立即返回; assign_attributes
没有这样的哈希检查。请参阅 ActiveRecord Attribute Assignment API documentation for attributes=
。
以下无效代码将通过简单地返回而不设置属性而静默失败:
@user.attributes = [ { model: "Sierra" }, { year: "2012" }, { looks: "Sexy" } ]
attributes=
会默默地表现得好像分配成功了,但实际上并非如此。
当 assign_attributes
尝试对封闭数组的哈希键进行字符串化时,此无效代码将引发异常:
@user.assign_attributes([ { model: "Sierra" }, { year: "2012" }, { looks: "Sexy" } ])
assign_attributes
将为 stringify_keys
引发 NoMethodError
异常,指示第一个参数不是哈希。异常本身并不能很好地说明实际原因,但确实发生异常这一事实非常重要。
这些情况之间的唯一区别是用于批量分配的方法:attributes=
静默成功,assign_attributes
引发异常以通知已发生错误。
这些示例可能看起来是做作的,但在一定程度上它们是做作的,但是在从 API 转换数据时很容易发生这种类型的错误,甚至只是使用一系列数据转换而忘记了 Hash[]
最终 {2 }。保留上面 50 行的一些代码,并从属性分配中删除 3 个函数,你就有了失败的秘诀。
Rails 3 的教训是:总是使用 assign_attributes
而不是 attributes=
。
导轨 4
在 Rails 4 中,attributes=
只是 assign_attributes
的别名。请参阅 ActiveRecord Attribute Assignment API documentation for attributes=
。
在 Rails 4 中,任何一种方法都可以互换使用。未能将 Hash 作为第一个参数传递将导致一个非常有用的异常:ArgumentError: When assigning attributes, you must pass a hash as an argument.
验证
如果您正在为 save
做准备工作前的任务,您可能也有兴趣在保存前进行验证。为此,您可以使用 valid?
和 invalid?
方法。两者都返回布尔值。如果未保存的模型通过所有验证,valid?
返回 true,否则返回 false。 invalid?
只是 valid?
的倒数
valid?
可以这样使用:
@user.assign_attributes{ model: "Sierra", year: "2012", looks: "Sexy" }.valid?
这将使您能够在调用 save
之前处理任何验证问题。
不定期副业成功案例分享
attr_accessible :is_admin, :as => :admin
;)attr_protected :is_admin
。或者:attr_accessible :name
在这个例子中,:is_admin 是受保护的。我还应该注意,尝试使用.assign_attributes
批量分配受保护的属性确实会引发ActiveModel::MassAssignmentSecurity::Error
,即使示例中没有显示。user.assign_attributes({ :name => 'Josh', :is_admin => true })
引发错误消息并且实际上没有设置用户的 name 属性。