Use ActiveRecord scopes, not class methods, in Rails to avoid errors

In Rails, scopes provide a shortcut your models’ most frequently used queries.

For instance, on a Widgets model, you might have a scope called available, which runs Widgets.where(“quantity_in_stock > 0”).

You can achieve the same effect with a class method on the Widgets model.

In either case,  Widget.available returns an ActiveRecord relation with the matching records, just as if you had called the where method directly.

If class methods and scopes do the same thing, why would you use one over the other?

Scopes, it turns out, are less error-prone.

To find out why, we need to examine a more complex query.

Say that widgets have a discontinuation_date. Once a widget hits that date, it is no longer available.

We’ll expand our available scope/method to take the discontinuation_date into account.

Here, we show widgets that are currently available and haven’t hit their discontinuation date.

Now, say you called Widget.available(nil).order(“title”).

The class method returns a nil object, and you receive an error stating that there is no method order on a nil object. Not good!

The scope, on the other hand, returns a blank ActiveRecord relation. Running order on a blank ActiveRecord relation returns that same relation. No error. Good!

Choose scopes over class methods in your models.

Scopes avoid the problem of nil objects, which make code messy and error-prone.

Scopes don’t return the dreaded nil objects, instead returning a blank relation on which you can run any ActiveRecord method. You could say they implement the null object pattern.

The most direct and bullet-proof way to avoid nil object errors is to avoid nil objects
If You Gaze Into Nil, Nil Gazes Also Into You by thoughtbot

For more details on the differences between class methods and scopes, check out Active Record Scopes vs. Class Methods on Plataformatic’s blog. brings Rails job offers to you. Free for candidates. Salaries from $75,000 to $250,000. Sign up now!

Leave a Reply