266
obj.update_attribute(:only_one_field, 'Some Value')
obj.update_attributes(field1: 'value', field2: 'value2', field3: 'value3')

这两个都将更新一个对象,而无需明确告诉 ActiveRecord 进行更新。

Rails API 说:

更新属性

更新单个属性并保存记录,而无需经过正常的验证过程。这对于现有记录上的布尔标志特别有用。当混入验证模块时,Base 中的常规 update_attribute 方法被替换为 this,默认情况下。

更新属性

从传入的 Hash 中更新所有属性并保存记录。如果对象无效,则保存失败,返回false。

因此,如果我不想验证对象,我应该使用#update_attribute. 如果我在 a 上有此更新怎么办#before_save,它会 stackoverflow 吗?

我的问题是#update_attribute也绕过了之前的保存或只是验证。

另外,将散列传递给的正确语法是什么#update_attributes...查看顶部的示例。

4

11 回答 11

345

请参考update_attribute。单击显示源,您将获得以下代码

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2614
2614:       def update_attribute(name, value)
2615:         send(name.to_s + '=', value)
2616:         save(false)
2617:       end

现在参考update_attributes并查看您获得的代码

      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2621
2621:       def update_attributes(attributes)
2622:         self.attributes = attributes
2623:         save
2624:       end

两者之间的区别是update_attribute使用save(false)update_attributes使用save或者你可以说save(true)

很抱歉描述太长,但我想说的很重要。save(perform_validation = true),如果perform_validation为假,它会绕过(跳过将是正确的词)与 .关联的所有验证save

对于第二个问题

此外,将散列传递给 update_attributes 的正确语法是什么...查看顶部的示例。

你的例子是正确的。

Object.update_attributes(:field1 => "value", :field2 => "value2", :field3 => "value3")

或者

Object.update_attributes :field1 => "value", :field2 => "value2", :field3 => "value3"

或者,如果您在哈希中获取所有字段数据和名称,请说params[:user]这里只使用

Object.update_attributes(params[:user])
于 2010-05-06T05:32:09.140 回答
74

提示:通过 Commit a7f4b0a1update_attribute在 Rails 4 中被弃用。它删除有利于.update_attributeupdate_column

于 2012-06-27T13:11:14.973 回答
17

更新属性

此方法在不调用基于模型的验证的情况下更新对象的单个属性。

obj = Model.find_by_id(params[:id])
obj.update_attribute :language, “java”

更新属性

此方法更新单个对象的多个属性并通过基于模型的验证。

attributes = {:name => “BalaChandar”, :age => 23}
obj = Model.find_by_id(params[:id])
obj.update_attributes(attributes)

希望这个答案能明确何时使用什么方法进行活动记录。

于 2013-01-21T10:42:46.110 回答
13

另外值得注意的是,与只更新指定属性的批量分配方法相反,update_attribute不需要将要更新的所需属性列入白名单来更新它。attr_accessibleupdate_attributesattr_accessible

于 2012-08-09T07:32:17.940 回答
8

update_attribute只是简单地更新模型的一个属性,但我们可以在update_attributes方法中传递多个属性。

例子:

user = User.last

#update_attribute
user.update_attribute(:status, "active")

它通过了验证

#update_attributes
user.update_attributes(first_name: 'update name', status: "active")

如果验证失败,它不会更新。

于 2015-04-20T12:26:58.897 回答
7

您可能有兴趣访问这篇关于分配属性或更新记录(更新到 Rails 4)的所有可能方法的博客文章update_attribute, update, update_column, update_columns etc. http://www.davidverhasselt.com/set-attributes-in-activerecord/。例如,它在运行验证、触摸对象的 updated_at 或触发回调等方面有所不同。

作为对 OP 问题的回答update_attribute,不会通过回调。

于 2015-07-14T07:21:56.700 回答
6

很好的答案。请注意,对于 ruby​​ 1.9 及更高版本,您可以(我认为应该)对 update_attributes 使用新的哈希语法:

Model.update_attributes(column1: "data", column2: "data")
于 2014-12-31T09:28:19.753 回答
5

update_attributeupdate_attributes相似,但有一个很大的区别:update_attribute 运行验证。

还:

  • update_attribute用于更新具有单个属性的记录。

    Model.update_attribute(:column_name, column_value1)
    
  • update_attributes用于更新具有多个属性的记录。

    Model.update_attributes(:column_name1 => column_value1, :column_name2 => column_value2, ...)
    

鉴于它们相似的名称和工作方式,这两种方法很容易混淆。因此,update_attribute正在被删除以支持update_column.

现在,在Rails4中,您可以Model.update_column(:column_name, column_value)Model.update_attribute(:column_name, column_value)

单击此处获取有关update_column.

于 2014-03-20T08:46:56.237 回答
4

要回答您的问题,请update_attribute跳过预保存“验证”,但它仍会运行任何其他回调等after_save。因此,如果您真的想“仅更新列并跳过任何 AR cruft”,那么您需要使用(显然)

Model.update_all(...)https://stackoverflow.com/a/7243777/32453

于 2014-05-21T18:38:21.387 回答
3

最近我遇到了update_attributevs.update_attributes和验证问题,名称如此相似,行为如此不同,如此混乱。

为了将哈希传递给update_attribute并绕过验证,您可以执行以下操作:

object = Object.new
object.attributes = {
  field1: 'value',
  field2: 'value2',
  field3: 'value3'
}
object.save!(validate: false)
于 2015-05-06T06:18:02.247 回答
1

我认为您的问题是,如果在 before_save 中有 update_attribute 会导致无限循环(在 before_save 回调中的 update_attribute 调用,最初由 update_attribute 调用触发)

我很确定它确实绕过了 before_save 回调,因为它实际上并没有保存记录。您还可以使用以下方法保存记录而不触发验证

模型.save false

于 2010-05-06T05:39:14.777 回答