Rails update_attributes没有保存?

是否存在不保存记录的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',但我想在一行上更新它们。

168198 次浏览

你可以使用'attributes'方法:

@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为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

它与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_attributesattributes=(它们是相同的)

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

  • __abc0 = __abc1 + __abc2
  • attributes= = assign_attributes的别名
  • update_attributes = deprecated, update的别名
< p > 来源: < br > https://github.com/rails/rails/blob/master/activerecord/lib/active_record/persistence.rb < br > https://github.com/rails/rails/blob/master/activerecord/lib/active_record/attribute_assignment.rb < / p > < p > 另一个小抄: < br > http://www.davidverhasselt.com/set-attributes-in-activerecord/#cheat-sheet < / p >

对于不保存的ActiveRecord模型的大量值分配,可以使用assign_attributesattributes=方法。这些方法在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试图对封闭数组的哈希键进行字符串化时,这段无效代码将引发异常:

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

assign_attributes将引发stringify_keysNoMethodError异常,表明第一个参数不是哈希。异常本身对实际原因没有太多的信息,但是异常确实发生的事实是非常重要的。

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

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

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

Rails 4

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

在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之前处理任何验证问题。