Don’t use default_scope. Ever.

When you would like a scope to be applied across all queries on a model, you can use default_scope. See more in the ActiveRecord Query Guide and Rails docs.


Where you have a blog system with posts that can be set to be hidden, for when you are writing a draft.

Instead of…

default_scope.

# app/models/post.rb
class Post < ActiveRecord::Base
  default_scope { where(hidden: false) }
end

Use…

…explicit scopes.

# app/models/post.rb
class Post < ActiveRecord::Base
  scope, :published -> { where(hidden: false) }
end

…then you can do…

Post.published

But why?

Two reasons. Both to do with avoiding later confusion and bug hunting.

Adding a default scope affects your model initialization. In the example, Post.new is defaulted to hidden = false whether you are expecting it or not.

Trying not to use your defined default scope is a pain. To remove the default_scope when you don’t need it you have to use the unscoped scope (!) which removes all applied conditions including associations.

i.e. Post.first.comments.unscoped would return every comment in your database, not just those for the first Post.

The explicit use of named scopes is a clearer solution. Using default_scope will lead to many hours of bug hunting. Don’t do it to yourself.

Where might I use it?

Seriously. Trust me on this one. It will bite you.

Last updated on October 1st, 2017