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.
update_attribute
statement inside a before_save
callback? I can't think of a good reason for this.
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.
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])
Tip: update_attribute
is being deprecated in Rails 4 via Commit a7f4b0a1. It removes update_attribute
in favor of update_column
.
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
update_column
is not deprecated, but update_columns(name: value)
is favored. reset_column
has been removed.
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.
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.
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.
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.
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")
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
.
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
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)
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
Success story sharing
Rails 3
. It says very plainly in the comments in the source that "Callbacks are invoked".update_attributes
is now an alias forupdate