Rails:update_attribute vs update_attributes

时间:2010-05-06 04:49:38

标签: ruby-on-rails callback update-attributes

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

这两个都将更新对象,而不必明确告知AR更新。

Rails API说:

for update_attribute

  

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

for update_attributes

  

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

因此,如果我不想验证对象,我应该使用update_attribute。如果我在before_save上有这个更新怎么办,它会堆栈溢出吗?

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

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

11 个答案:

答案 0 :(得分:318)

请参阅update_attribute。点击show source后,您将获得以下代码

      # 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为false,则绕过与save关联的所有validations都会绕过(跳过将是正确的词)。

第二个问题

  

此外,将散列传递给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])

答案 1 :(得分:74)

提示: update_attribute已在Rails 4中通过Commit a7f4b0a1弃用。它会移除update_attribute,转而使用update_column

答案 2 :(得分:15)

<强> update_attribute

此方法更新对象的单个属性,而不调用基于模型的验证。

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

<强> update_attributes方法

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

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

希望这个答案能够清除何时使用什么方法的活动记录。

答案 3 :(得分:11)

另外值得注意的是,对于update_attribute,要更新的所需属性不需要与attr_accessible一起列入白名单来更新它,而不是质量分配方法update_attributes这只会更新attr_accessible指定的属性。

答案 4 :(得分:6)

很棒的答案。 请注意,至于ruby 1.9及以上,你可以(我认为应该)使用update_attributes的新哈希语法:

Model.update_attributes(column1: "data", column2: "data")

答案 5 :(得分:6)

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")

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

答案 6 :(得分:5)

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

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

答案 7 :(得分:4)

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)

Click here获取有关update_column的更多信息。

答案 8 :(得分:3)

要回答您的问题,update_attribute会跳过预先保存&#34;验证&#34;但它仍然运行任何其他回调,如after_save等。所以如果你真的想要&#34;只需更新列并跳过任何AR cruft&#34;然后你需要使用(显然)

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

答案 9 :(得分:2)

最近我遇到了update_attributeupdate_attributes和验证问题,因此名称相似,行为不同,令人困惑。

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

object = Object.new
object.attributes = {
  field1: 'value',
  field2: 'value2',
  field3: 'value3'
}
object.save!(validate: false)

答案 10 :(得分:1)

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

我很确定它绕过了before_save回调,因为它实际上并没有保存记录。您还可以使用

保存记录而不触发验证

Model.save false