ActiveRecord's update_column
Using update_column is usually a mistake
2016-08-17
#update_column
used to be a critical performance tool before Rails had dirty
attribute tracking. Now that ActiveRecord manages dirty tracking for us, there
are very few legitimate uses of this function with a lot of serious down-sides.
When you use update_column
to change a model, here’s what you get:
- Validation is skipped
- Callbacks are skipped
updated_at
/updated_on
and ‘lock_version’ are not updated
In the general case, these two calls to exactly the same thing:
|
|
|
|
What you might save in line count you lose in clarity. You also expose yourself
to unnecessary risks. The second option is much easier for a less experienced
engineer to mis-read and to use inefficiently (by, for example, making two
update_column
calls in the same function). Choosing to skip validation and
callbacks should always be explicit so it is not overlooked and so that the
author has an opportunity to add a comment explaining why they need a special
exception to their own safeguards.
Often when I see extensive use of update_column
in a Rails app, it’s being
used to store one of multiple text fields an a module, presumable to avoid the
saving/loading of all the record’s text field. Unfortunately, it’s not actually
providing much if any value in these cases, and it definitely doesn’t save
the application from poor data design. A Next Level Developer avoids unnecessary
optimizations, preferring to write predictable, clean, and transparent code.
NOTE: ActiveRecord has another method, update_attribute
, which is equally to
be avoided. This version skips validation, just like update_column
, but does
not skip callbacks and does update automatic columns like lock_version
.
Basically, it’s the worst of both worlds.