Different Ways to Set Attributes in ActiveRecord (Rails 3)

Last revisited on , originally published on . Ruby On Rails Rails 3

Rails 3 allows the developer to change ActiveRecord attributes in various ways. Each one does it slightly differently with sometimes unique side-effects. It’s important you understand which method to use, so here’s a cheat sheet. Scroll further down for an explanation of each.

This article was written for Rails 3. Check out the updated Rails 4 version.

Cheat Sheet

Method Uses Default Accessor Mass Assignment Protection Saved to Database Validations
attribute= Yes No No n/a
write_attribute No No No n/a
update_attribute Yes No Yes No
attributes= Yes Yes1 No n/a
update_attributes Yes Yes Yes Yes

In Depth

For the following examples we’ll set the name attribute on the user object.

user.name = "Rob"

This regular assignment is the most common and easiest to use. It is the default write accessor generated by Rails. The name attribute will be marked as dirty and the change will not be sent to the database yet.

You can undo the change by calling reload! or save the change to the database by calling save.

user.write_attribute(:name, "Rob")

This is the method that is called by the default accessor above. A synonym for this function is user[:name] = "Rob". It also has a read_attribute counterpart.

Just like above, this method does not yet change the attribute in the database. Use this method anywhere you need to bypass the default write accessor above, for example when you want to write a custom attribute= writer.

user.update_attribute(:name, "Rob")

This method will change the attribute in the model and pass it straight to the database, without running any validations.

Two gotchas:

  • Any other changed attributes are also saved to the database.
  • Validations are skipped so you could end up with invalid data.

Because of that last quirk it’s a good practice to use update_attributes instead.

user.attributes = {name: "Rob"}

This method will set all the attributes you pass it, except those who are protected from mass assignment if you’re using attr_protected or attr_accessible. The changes are not saved to the database.

You can override the mass assignment protection by passing false:

user.send(:attributes=, name: "Rob", false)

user.update_attributes(name: "Rob")

This method changes the attributes of the model, checks the validations, and updates the record in the database if it validates. Since it uses the above attributes=method, attributes protected from mass assignment are not changed.

Note that just like update_attribute this method also saves other changed attributes to the database.

More

If you want to understand more about these methods I suggest you check out their source code. Each time it’s only a couple of lines and it will really broaden your understanding of how Rails works!

  1. Mass Assignment Protection for attributes= is overridable.

David Verhasselt

Senior full-stack engineer with 5 years of experience building web applications for clients all over the world.

Interested in working together?

Find out what I can do for you or get in touch!

Like this? Sign up to get regular updates