Rails:update_attribute vs update_attributes

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

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

Rails API说:

为update_attribute

更新单个属性并保存logging,而不需要经过正常的validation过程。 这对于现有logging上的布尔标志特别有用。 Base中的常规update_attribute方法在validation模块混入时replace为默认值。

为update_attributes

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

所以如果我不想validation对象,我应该使用update_attribute。 如果我在before_save上有这个更新,会怎样呢?

我的问题是,update_attribute也绕过之前保存或只是validation。

此外,什么是正确的语法传递给update_attributes散列…检查我的例子在顶部。

请参考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为false,则绕过(跳过将是合适的词)与save相关的所有validation 。

对于第二个问题

此外,什么是正确的语法传递给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]) 

提示: update_attribute在Rails 4中通过Commit a7f4b0a1被弃用。 它将删除update_attribute ,以update_column

update_attribute

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

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

update_attributes方法

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

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

希望这个答案会清楚什么时候使用什么方法的主动logging。

另外值得注意的是,使用update_attribute ,需要更新的期望属性不需要用attr_accessible进行白名单来更新,而不是使用只会更新attr_accessible指定属性的批量分配方法update_attributes

很好的答案。 注意,对于ruby 1.9和以上版本,你可以(而且我认为应该)使用new_attributes的新哈希语法:

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

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

例:

 user = User.last #update_attribute user.update_attribute(:status, "active") 

它通过validation

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

如果validation失败,它不会更新。

您可能有兴趣访问此博客文章,了解分配属性或更新logging(更新到Rails 4)的所有可能方法: update_attribute, update, update_column, update_columns etc. 。http: update_attribute, update, update_column, update_columns etc. in-activerecord / 。 例如,它在诸如运行validation,触摸对象的updated_at或触发callback等方面有所不同。

作为OP的问题的答案update_attribute不通过callback。

为了回答你的问题,update_attribute跳过预保存“validation”,但它仍然运行after_save等任何其他callback。所以,如果你真的想“只更新列和跳过任何AR cruft”,那么你需要使用(显然)

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

最近我遇到了update_attributeupdate_attributes和validation问题,所以类似的名字,如此不同的行为,如此混乱。

为了将hash传递给update_attribute并绕过validation,你可以这样做:

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

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

也:

  • update_attribute用来更新单个属性的logging。

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

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

这两种方法由于类似的名字和作品而很容易混淆。 因此, update_attribute正在被删除,以支持update_column

现在,在Rails4中,你可以在Model.update_attribute Model.update_column(:column_name, column_value)的地方使用Model.update_attribute(:column_name, column_value)

点击这里获取更多关于update_column信息。

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

我很确定它确实绕过了before_savecallback,因为它实际上并没有保存logging。 您也可以保存logging,而不用通过使用触发validation

Model.save错误

Interesting Posts