本文翻译自:Rails update_attributes without save?
Is there an alternative to update_attributes that does not save the record? 有没有替代update_attributes而不保存记录的方法?
So I could do something like: 所以我可以做类似的事情:
@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
BTW, I know I can @car.model = 'Sierra'
, but I want to update them all on one line. 顺便说一句,我知道我可以@car.model = 'Sierra'
,但是我想一次全部更新它们。
#1楼
参考:https://stackoom.com/question/SPHC/Rails-update-attributes没有保存
#2楼
I believe what you are looking for is assign_attributes
. 我相信您正在寻找的是assign_attributes
。
It's basically the same as update_attributes but it doesn't save the record: 它与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
#3楼
You can use assign_attributes
or attributes=
(they're the same) 您可以使用assign_attributes
或attributes=
(它们相同)
Update methods cheat sheet (for Rails 6): 更新方法备忘单(适用于Rails 6):
-
update
=assign_attributes
+save
update
=assign_attributes
+save
-
attributes=
= alias ofassign_attributes
attributes=
=assign_attributes
别名 -
update_attributes
= deprecated, alias ofupdate
update_attributes
=已弃用,update
别名
Source: 资源:
https://github.com/rails/rails/blob/master/activerecord/lib/active_record/persistence.rb 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 https://github.com/rails/rails/blob/master/activerecord/lib/active_record/attribute_assignment.rb
Another cheat sheet: 另一个备忘单:
http://www.davidverhasselt.com/set-attributes-in-activerecord/#cheat-sheet http://www.davidverhasselt.com/set-attributes-in-activerecord/#cheat-sheet
#4楼
For mass assignment of values to an ActiveRecord model without saving, use either the assign_attributes
or attributes=
methods. 要在不保存的情况下将值批量分配给ActiveRecord模型,请使用assign_attributes
或attributes=
方法。 These methods are available in Rails 3 and newer. 这些方法在Rails 3和更高版本中可用。 However, there are minor differences and version-related gotchas to be aware of. 但是,需要注意一些细微的差异以及与版本相关的陷阱。
Both methods follow this usage: 两种方法都遵循这种用法:
@user.assign_attributes{ model: "Sierra", year: "2012", looks: "Sexy" }
@user.attributes = { model: "Sierra", year: "2012", looks: "Sexy" }
Note that neither method will perform validations or execute callbacks; 注意,这两种方法都不会执行验证或执行回调。 callbacks and validation will happen when save
is called. 调用save
时将发生回调和验证。
Rails 3 导轨3
attributes=
differs slightly from assign_attributes
in Rails 3. attributes=
will check that the argument passed to it is a Hash, and returns immediately if it is not; attributes=
与Rails 3中的assign_attributes
略有不同assign_attributes
attributes=
将检查传递给它的参数是否为哈希,如果不是,则立即返回;否则,返回false。 assign_attributes
has no such Hash check. assign_attributes
没有此类哈希检查。 See the ActiveRecord Attribute Assignment API documentation for attributes=
. 请参阅ActiveRecord属性分配API文档以获取attributes=
。
The following invalid code will silently fail by simply returning without setting the attributes: 以下无效代码将通过仅返回而不设置属性而静默失败:
@user.attributes = [ { model: "Sierra" }, { year: "2012" }, { looks: "Sexy" } ]
attributes=
will silently behave as though the assignments were made successfully, when really, they were not. attributes=
将默默地表现为分配已成功完成,实际上却没有成功。
This invalid code will raise an exception when assign_attributes
tries to stringify the hash keys of the enclosing array: 当assign_attributes
尝试对封闭数组的哈希键进行字符串化时,此无效代码将引发异常:
@user.assign_attributes([ { model: "Sierra" }, { year: "2012" }, { looks: "Sexy" } ])
assign_attributes
will raise a NoMethodError
exception for stringify_keys
, indicating that the first argument is not a Hash. assign_attributes
将引发NoMethodError
异常stringify_keys
,表明第一个参数是不是哈希。 The exception itself is not very informative about the actual cause, but the fact that an exception does occur is very important. 异常本身并不能很好地说明实际原因,但是异常确实发生的事实非常重要。
The only difference between these cases is the method used for mass assignment: attributes=
silently succeeds, and assign_attributes
raises an exception to inform that an error has occurred. 这两种情况之间唯一的区别是用于批量分配的方法: attributes=
默默地成功,而assign_attributes
引发异常以通知已发生错误。
These examples may seem contrived, and they are to a degree, but this type of error can easily occur when converting data from an API, or even just using a series of data transformation and forgetting to Hash[]
the results of the final .map
. 这些示例在某种程度上似乎是人为的,但是当从API转换数据,甚至只是使用一系列数据转换而忘记将最终.map
的结果传递给Hash[]
时,此类错误很容易发生。 。 Maintain some code 50 lines above and 3 functions removed from your attribute assignment, and you've got a recipe for failure. 保持上面的50行代码和从属性分配中删除的3个功能,您将获得失败的秘诀。
The lesson with Rails 3 is this: always use assign_attributes
instead of attributes=
. Rails 3的课程是: 始终使用assign_attributes
而不是attributes=
。
Rails 4 滑轨4
In Rails 4, attributes=
is simply an alias to assign_attributes
. 在Rails 4中, attributes=
只是assign_attributes
的别名。 See the ActiveRecord Attribute Assignment API documentation for attributes=
. 请参阅ActiveRecord属性分配API文档以获取attributes=
。
With Rails 4, either method may be used interchangeably. 对于Rails 4,这两种方法都可以互换使用。 Failure to pass a Hash as the first argument will result in a very helpful exception: ArgumentError: When assigning attributes, you must pass a hash as an argument.
未能将哈希作为第一个参数传递将导致一个非常有用的异常: ArgumentError: When assigning attributes, you must pass a hash as an argument.
Validations 验证方式
If you're pre-flighting assignments in preparation to a save
, you might be interested in validating before save, as well. 如果您在准备save
前进行飞行检查,那么您可能也有兴趣在保存之前进行验证。 You can use the valid?
您可以使用valid?
and invalid?
invalid?
methods for this. 方法。 Both return boolean values. 两者都返回布尔值。 valid?
returns true if the unsaved model passes all validations or false if it does not. 如果未保存的模型通过所有验证,则返回true;否则,返回false。 invalid?
is simply the inverse of valid?
就是valid?
的反函数valid?
valid?
can be used like this: 可以这样使用:
@user.assign_attributes{ model: "Sierra", year: "2012", looks: "Sexy" }.valid?
This will give you the ability to handle any validations issues in advance of calling save
. 这将使您能够在调用save
之前处理所有验证问题。
#5楼
You can use the 'attributes' method: 您可以使用“属性”方法:
@car.attributes = {:model => 'Sierra', :years => '1990', :looks => 'Sexy'}
Source: http://api.rubyonrails.org/classes/ActiveRecord/Base.html 来源: http : //api.rubyonrails.org/classes/ActiveRecord/Base.html
attributes=(new_attributes, guard_protected_attributes = true) Allows you to set all the attributes at once by passing in a hash with keys matching the attribute names (which again matches the column names). attributes =(new_attributes,guard_protected_attributes = true)允许您通过传入散列值与属性名称匹配(又与列名称匹配)的键来一次设置所有属性。
If guard_protected_attributes is true (the default), then sensitive attributes can be protected from this form of mass-assignment by using the attr_protected macro. 如果guard_protected_attributes为true(默认设置),则可以使用attr_protected宏保护敏感属性免受这种形式的批量分配。 Or you can alternatively specify which attributes can be accessed with the attr_accessible macro. 或者,您也可以指定可以使用attr_accessible宏访问哪些属性。 Then all the attributes not included in that won't be allowed to be mass-assigned. 这样一来,所有未包含在其中的属性都将无法进行大规模分配。
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