Encapsulating queries in a Rails model

Ruby on Rails / Active Record

That is the quick one: there is no doubt that it’s better to isolate database query logic from other classes such as services or controllers. If you want to put it in a model you can consider these two options:

Class method

def self.recent
  order(created_at: :desc)

ActiveRecord scope API

scope :recent, -> { order(created_at: :desc) }

Which one?

You may say it’s just a matter of taste because Active Record will convert a scope into a class method anyway but:

Scopes are always chainable

Even if you use condition inside the definition, like this:

scope :by_email, -> |email| { where(email: email) if email.present? }

having the same with class method would not allow you to chain methods

def self.by_email(email)
  where(email: email) if email.present?

because self.by_email would return nil when email would be blank

So which one?

Pick up the one that your team like the most and try to stick to selected convention across the whole app.