270
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.

BinaryButterfly
  • 18,137
  • 13
  • 50
  • 91
thenengah
  • 42,557
  • 33
  • 113
  • 157
  • 1
    Why do you want to put an `update_attribute` statement inside a `before_save` callback? I can't think of a good reason for this. – Daniel Pietzsch May 06 '10 at 05:54
  • 1
    I have objects that need to be updated based on the what the updated object's amount is. What is better way? – thenengah May 06 '10 at 06:13
  • Am I right, that the objects you need to update are attributes of the object you are saving? If yes, then you could just set them, and they will be updated along with the object that is saved anyway (because they are set within a `before_save` callback). F.e. instead of `update_attribute(:discount, 0.1) if amount > 100` you could do `discount = 0.1 if amount > 100`. `update_attribute` calls `save` on the object, which is unnecessary in this case, since the statement is inside a `before_save` callback and will get saved anyway. I hope that makes sense. – Daniel Pietzsch May 07 '10 at 03:19
  • Yes and no. However, the status of the objects that you are referring to is contingent upon other conditions that cannot be processed before the save. – thenengah May 18 '10 at 04:02
  • 3
    as a note, these methods skip validation but will *still perform* callbacks, like after_save ... – rogerdpack Jan 27 '13 at 05:15

11 Answers11

352

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])
Andre Figueiredo
  • 12,930
  • 8
  • 48
  • 74
Salil
  • 46,566
  • 21
  • 122
  • 156
  • 7
    Your statement about callbacks is incorrect, at least in `Rails 3`. It says very plainly in [the comments in the source](https://github.com/rails/rails/blob/v3.2.11/activerecord/lib/active_record/persistence.rb#L173) that "Callbacks are invoked". – Batkins Jan 29 '13 at 20:39
  • I second what @Batkins says – Raf Jul 16 '13 at 15:53
  • 4
    @Batkins still validations are not run - that's the most important part :) – Tigraine Oct 29 '13 at 08:44
  • 3
    The links above are no longer accurate at least as of **Rails 5.1**. These methods were moved to ActiveRecord::Persistence. You can find the updated info here: [update attribute](http://api.rubyonrails.org/classes/ActiveRecord/Persistence.html#method-i-update_attribute) and here [update_attributes](http://api.rubyonrails.org/classes/ActiveRecord/Persistence.html#method-i-update_attributes) Note: `update_attributes` is now an alias for `update` – tgf Feb 27 '18 at 01:54
  • 1
    This answer is rather outdated - links are dead, quoted source code Is no longer relevant in recent ActiveRecord versions. – BinaryButterfly Apr 16 '21 at 10:03
75

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

Matt
  • 941
  • 6
  • 14
  • 51
    This is no longer true; the method has been re-added. See https://github.com/rails/rails/pull/6738#issuecomment-39584005 – Dennis Apr 04 '14 at 16:43
  • 26
    `update_attribute` skips validation, but respects callbacks, `update_column` will skip both validation and callbacks and wont update `:updated_at`, `update` is the normal function that will respect both callbacks and validation – Mohammad AbuShady Sep 15 '14 at 11:25
  • 2
    will they make up their minds already. reset_column, update_column deprecated also. – ahnbizcad Sep 15 '14 at 17:57
  • 2
    `update_column` is not deprecated, but `update_columns(name: value)` is favored. `reset_column` has been removed. – onebree Jul 07 '15 at 20:03
18

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.

BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
13

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.

Kibet Yegon
  • 2,763
  • 2
  • 25
  • 32
9

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.

Arslan Ali
  • 17,418
  • 8
  • 58
  • 76
Shoaib Malik
  • 373
  • 4
  • 8
7

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.

adamliesko
  • 1,887
  • 1
  • 14
  • 21
6

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")
Ziv Galili
  • 1,405
  • 16
  • 20
5

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.

AkaZecik
  • 980
  • 2
  • 11
  • 16
uma
  • 2,932
  • 26
  • 20
4

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

rogerdpack
  • 62,887
  • 36
  • 269
  • 388
3

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)
Wojciech Bednarski
  • 6,033
  • 9
  • 49
  • 73
1

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

concept47
  • 30,257
  • 12
  • 52
  • 74