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 thescope
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.