Sam 山
Sam 山

Reputation: 42865

Rails: #update_attribute vs #update_attributes

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

Both of these will update an object without having to explicitly tell ActiveRecord to update.

Rails API says:

update_attribute

Updates a single attribute and saves the record without going through the normal validation procedure. This is especially useful for boolean flags on existing records. The regular update_attribute method in Base is replaced with this when the validations module is mixed in, which it is by default.

update_attributes

Updates all the attributes from the passed-in Hash and saves the record. If the object is invalid, the saving will fail and false will be returned.

So if I don't want to have the object validated I should use #update_attribute. What if I have this update on a #before_save, will it stackoverflow?

My question is does #update_attribute also bypass the before save or just the validation.

Also, what is the correct syntax to pass a hash to #update_attributes ... check out my example at the top.

Upvotes: 273

Views: 341967

Answers (11)

rogerdpack
rogerdpack

Reputation: 66711

To answer your question, update_attribute skips pre save "validations" but it still runs any other callbacks like after_save etc. So if you really want to "just update the column and skip any AR cruft" then you need to use (apparently)

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

Upvotes: 4

Salil
Salil

Reputation: 47472

Please refer to update_attribute. On clicking show source you will get following code

      # 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

and now refer update_attributes and look at its code you get

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

the difference between two is update_attribute uses save(false) whereas update_attributes uses save or you can say save(true).

Sorry for the long description but what I want to say is important. save(perform_validation = true), if perform_validation is false it bypasses (skips will be the proper word) all the validations associated with save.

For second question

Also, what is the correct syntax to pass a hash to update_attributes... check out my example at the top.

Your example is correct.

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

or

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

or if you get all fields data & name in a hash say params[:user] here use just

Object.update_attributes(params[:user])

Upvotes: 355

uma
uma

Reputation: 2952

update_attribute and update_attributes are similar, but with one big difference: update_attribute does not run validations.

Also:

  • update_attribute is used to update record with single attribute.

    Model.update_attribute(:column_name, column_value1)
    
  • update_attributes is used to update record with multiple attributes.

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

These two methods are really easy to confuse given their similar names and works. Therefore, update_attribute is being removed in favor of update_column.

Now, in Rails4 you can use Model.update_column(:column_name, column_value) at the place of Model.update_attribute(:column_name, column_value)

Click here to get more info about update_column.

Upvotes: 5

Shoaib Malik
Shoaib Malik

Reputation: 373

update_attribute simply updates only one attribute of a model, but we can pass multiple attributes in update_attributes method.

Example:

user = User.last

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

It pass the validation

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

it doesn't update if validation fails.

Upvotes: 9

adamliesko
adamliesko

Reputation: 1915

You might be interested in visiting this blog post concerning all the possible ways to assign an attribute or update record (updated to Rails 4) update_attribute, update, update_column, update_columns etc. http://www.davidverhasselt.com/set-attributes-in-activerecord/. For example it differs in aspects such as running validations, touching object's updated_at or triggering callbacks.

As an answer to the OP's question update_attribute does not by pass callbacks.

Upvotes: 7

Wojciech Bednarski
Wojciech Bednarski

Reputation: 6373

Recently I ran into update_attribute vs. update_attributes and validation issue, so similar names, so different behavior, so confusing.

In order to pass hash to update_attribute and bypass validation you can do:

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

Upvotes: 3

Ziv Galili
Ziv Galili

Reputation: 1445

Great answers. notice that as for ruby 1.9 and above you could (and i think should) use the new hash syntax for update_attributes:

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

Upvotes: 6

Balachandar1887229
Balachandar1887229

Reputation: 456

update_attribute

This method update single attribute of object without invoking model based validation.

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

update_attributes

This method update multiple attribute of single object and also pass model based validation.

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

Hope this answer will clear out when to use what method of active record.

Upvotes: 18

Kibet Yegon
Kibet Yegon

Reputation: 2823

Also worth noting is that with update_attribute, the desired attribute to be updated doesn't need to be white listed with attr_accessible to update it as opposed to the mass assignment method update_attributes which will only update attr_accessible specified attributes.

Upvotes: 13

Matt
Matt

Reputation: 951

Tip: update_attribute is being deprecated in Rails 4 via Commit a7f4b0a1. It removes update_attribute in favor of update_column.

Upvotes: 76

concept47
concept47

Reputation: 31726

I think your question is if having an update_attribute in a before_save will lead to and endless loop (of update_attribute calls in before_save callbacks, originally triggered by an update_attribute call)

I'm pretty sure it does bypass the before_save callback since it doesn't actually save the record. You can also save a record without triggering validations by using

Model.save false

Upvotes: 1

Related Questions