提问



有没有替换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[51]


它与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

其它参考1


您可以使用assign_attributesattributes=(它们相同)


更新方法备忘单(适用于Rails 4):



  • update_attributes=assign_attributes + save

  • attributes==assign_attributes
  • 的别名
  • update=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[52][53]


另一个备忘单:

http://www.davidverhasselt.com/set-attributes-in-activerecord/#cheat-sheet[54]

其它参考2


您可以使用属性方法:


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


资料来源:http://api.rubyonrails.org/classes/ActiveRecord/Base.html [55]


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

其它参考3


要在不保存的情况下将值分配给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=将检查传递给它的参数是否为Hash,如果不是则立即返回; assign_attributes没有这样的哈希检查。请参阅attributes=的ActiveRecord属性分配API文档。[56]


只需在不设置属性的情况下返回,以下无效代码将无声地失败:


@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[]最终结果时,很容易发生这种类型的错误.map。保留一些代码50行以上,并从属性赋值中删除3个函数,并且您已经找到了失败的秘诀。


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


Rails 4



在Rails 4中,attributes=只是assign_attributes的别名。请参阅attributes=的ActiveRecord属性分配API文档。[57]


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