ActiveRecord Dangers Cheat Sheet

One of my least-favorite Rails scenarios goes like this:

1

2

3

4

pry>user=User.find(id)

pry>user.bio="a valid bio"

pry>user.save!

ActiveRecord::RecordInvalid:Validationfailed:Namecan'tbeblank

I pulled a record from the database, made a valid change, and was unable to save because the record I got from the database was invalid. This is especially frustrating when I make a larger change and scour hundreds of lines of intermedia code before I realize that
User.find(id).save! would’ve failed just the same.

What’s happening here?

ActiveRecord has a number of useful methods that also skip your setters, validations, and callbacks. They’re fast and convenient, but make it easy to save invalid data or update existing data into an invalid state. Rather than being namespaced into a module or using a convention like “bang methods are unsafe”, most have names that are small variations on safe methods.

destroy is safe,
delete is not.
update and
update! are both safe but
update_column and
update_columns are both unsafe.
update_attributes is safe,
update_attribute is not – wait, or do I have those the wrong way around?

There’s no structure, you’d have to memorize them, so I made a cheat sheet of the safe and unsafe methods on model classes and instances.

Most of the unsafe methods are useful for performance reasons, so I’m not saying to never use them. But I’d like to see them only used from a class or method that has “unsafe” in the name, put a big warning sign on them so that they don’t slip into normal use of your code.

I’ve got more ideas for locating and preventing persisted invalid data in the works for a RailsConf 2016 talk – join the mailing list below for early peeks at them.

Valent.io Newsletter

Let’s write better code. I’ll send articles every two weeks or so on functional programming, especially applying its concepts to dynamic languages like Ruby.