Ruby on Rails ActiveRecord scopes vs class methods

Scopes are just class methods. Internally Active Record converts a scope into a class method.

"There is no difference between them" or “it is a matter of taste”. I tend to agree with both sentences, but I’d like to show some slight differences that exist between both. This blogs explains the difference very well.


From the fine guide:

14 Scopes
[...]
To define a simple scope, we use the scope method inside the class, passing the query that we'd like to run when this scope is called:

class Article < ActiveRecord::Base
  scope :published, -> { where(published: true) }
end

This is exactly the same as defining a class method, and which you use is a matter of personal preference:

class Article < ActiveRecord::Base
  def self.published
    where(published: true)
  end
end

Note in particular:

This is exactly the same as defining a class method, and which you use is a matter of personal preference

And a little further (the Rails3 guide says the same thing here BTW):

14.1 Passing in arguments
[...]
Using a class method is the preferred way to accept arguments for scopes.

So which you use is a matter of preference and it is even recommended that you use class methods for scopes that take arguments.

Using scope is mostly a notational issue. If you say scope :whatever then you're explicitly saying that whatever is meant to be a query builder; if you say def self.whatever then you're not implying anything about the intent of the whatever method, you're just defining some class method that may or may not behave like a scope.

Of course, 14.1 makes a mess of this notational distinction by recommending that you not use scope when your scope takes arguments. Also keep in mind that in Rails3 you could say:

scope :published, where(published: true)

so an argumentless scope was visually "clean" and terse but adding a lambda to handle arguments would make it look messier:

scope :pancakes, ->(x) { where(things: x) }

But Rails4 wants lambdas even for argumentless scopes the distinction makes even less sense now.

I suspect that the difference is historical at this point. Scopes were probably something special back in the before times but became plain old class methods in the Rails3 era to cut down on duplication and to better mesh with the new query interface that came with Rails3.


So you can skip scope and go straight to class methods if you wish. You're even encouraged to do so when your scope takes arguments.