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

顺便说一下,我知道我可以@车。model = 'Sierra',但我想在一行中更新它们。


当前回答

我相信您正在寻找的是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

其他回答

对于大量值分配到ActiveRecord模型而不保存,使用assign_attributes或attributes=方法。这些方法在Rails 3和更新版本中可用。但是,有一些小的差异和版本相关的陷阱需要注意。

这两种方法都遵循以下用法:

@user.assign_attributes{ model: "Sierra", year: "2012", looks: "Sexy" }

@user.attributes = { model: "Sierra", year: "2012", looks: "Sexy" }

注意,这两个方法都不会执行验证或执行回调;调用save时将发生回调和验证。

Rails 3

attributes=与Rails 3中的assign_attributes略有不同。attributes=将检查传递给它的参数是否为哈希,如果不是则立即返回;assign_attributes没有这样的哈希检查。有关attributes=,请参阅ActiveRecord属性赋值API文档。

下面的无效代码将在不设置属性的情况下直接返回,从而无声地失败:

@user.attributes = [ { model: "Sierra" }, { year: "2012" }, { looks: "Sexy" } ]

Attributes =会默默地表现得好像赋值成功了一样,但实际上并没有。

当assign_attributes试图string化封闭数组的哈希键时,这段无效的代码将引发异常:

@user.assign_attributes([ { model: "Sierra" }, { year: "2012" }, { looks: "Sexy" } ])

assign_attributes将为stringify_keys引发一个NoMethodError异常,表明第一个参数不是哈希。异常本身并不能很好地说明实际的原因,但是异常确实发生的事实是非常重要的。

这些情况之间的唯一区别是用于批量分配的方法:attributes=无声地成功,而assign_attributes引发一个异常,通知发生了错误。

这些例子看起来可能是人为的,而且在某种程度上确实如此,但是当从API转换数据时,或者甚至只是使用一系列数据转换而忘记对最终的.map结果进行Hash时,这种类型的错误很容易发生。维护一些超过50行的代码,并从属性赋值中删除3个函数,就会导致失败。

Rails 3的教训是:总是使用assign_attributes而不是attributes=。

Rails 4

在Rails 4中,attributes=只是assign_attributes的别名。有关attributes=,请参阅ActiveRecord属性赋值API文档。

在Rails 4中,这两种方法都可以互换使用。未能将哈希作为第一个参数传递将导致一个非常有用的异常:ArgumentError:当分配属性时,您必须将哈希作为参数传递。

验证

如果你正在为保存而准备飞行任务,你可能也有兴趣在保存前进行验证。你可以使用有效的?和无效的?方法。两者都返回布尔值。有效吗?如果未保存的模型通过所有验证,则返回true;如果未通过验证,则返回false。无效的?仅仅是有效的逆吗?

有效吗?可以这样使用:

@user.assign_attributes{ model: "Sierra", year: "2012", looks: "Sexy" }.valid?

这将使您能够在调用save之前处理任何验证问题。

我相信您正在寻找的是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

你可以使用'attributes'方法:

@car.attributes = {:model => 'Sierra', :years => '1990', :looks => 'Sexy'}

来源:http://api.rubyonrails.org/classes/ActiveRecord/Base.html

属性=(new_attributes, guard_protected_attributes = true) 允许您通过传入与属性名匹配的键的散列(再次匹配列名)来一次性设置所有属性。

如果guard_protected_attributes为true(默认值),那么可以使用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

你可以使用assign_attributes或者attributes=(它们是一样的)

更新方法小抄(适用于Rails 6):

更新= assign_attributes +保存 Attributes = = assign_attributes的别名 Update_attributes = deprecated,更新的别名

来源: 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