概要
原著者の許諾を得て翻訳・公開いたします。
- 英語記事: Encapsulating queries in a Rails model - Ruby on Rails / ActiveRecord
- 原文公開日: 2018/01/01
- 著者: Paweł Dąbrowski
Rails: モデルのクエリをカプセル化する2つの方法(翻訳)
要点: サービスやコントローラなどのクラスからデータベースクエリのロジックを分離することは間違いなく優れた方法です。ロジックをモデルに置く場合、次の2とおりの方法が使えます。
1. クラスメソッド化する
def self.recent
order(created_at: :desc)
end
2. ActiveRecordのスコープAPIを使う
scope :recent, -> { order(created_at: :desc) }
どちらにすればよいか
ActiveRecordのスコープはどっちみちクラスメソッドに変換されるので、どちらを選ぶかは見た目の問題に過ぎません。ただし、
スコープはいついかなるときでもチェイン可能である点がポイントです。
次のように、スコープの定義内に条件を含めた場合でもチェインできます。
scope :by_email, -> |email| { where(email: email) if email.present? }
クラスメソッドで同じことをした場合、メソッドをチェインできないことがあります。
def self.by_email(email)
where(email: email) if email.present?
end
チェインできない理由は、self.by_email
のemail
がblankの場合にnil
を返していることです。
ではどちらにすればよいか
チームの好みに合わせて決めればよいでしょう。その代わり、一度決めたらアプリ全体でその書き方を統一します。