Rails tips: モデルのクエリをカプセル化する2つの方法(翻訳)

概要

原著者の許諾を得て翻訳・公開いたします。

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_emailemailがblankの場合にnilを返していることです。

ではどちらにすればよいか

チームの好みに合わせて決めればよいでしょう。その代わり、一度決めたらアプリ全体でその書き方を統一します。

関連記事

Railsのdefault_scopeは使うな、絶対(翻訳)

肥大化したActiveRecordモデルをリファクタリングする7つの方法(翻訳)

デザインも頼めるシステム開発会社をお探しならBPS株式会社までどうぞ 開発エンジニア積極採用中です! Ruby on Rails の開発なら実績豊富なBPS

この記事の著者

hachi8833

Twitter: @hachi8833、GitHub: @hachi8833 コボラー、ITコンサル、ローカライズ業界、Rails開発を経てTechRachoの編集・記事作成を担当。 これまでにRuby on Rails チュートリアル第2版の監修および半分程度を翻訳、Railsガイドの初期翻訳ではほぼすべてを翻訳。その後も折に触れて更新翻訳中。 かと思うと、正規表現の粋を尽くした日本語エラーチェックサービス enno.jpを運営。 実は最近Go言語が好きで、Goで書かれたRubyライクなGoby言語のメンテナーでもある。 仕事に関係ないすっとこブログ「あけてくれ」は2000年頃から多少の中断をはさんで継続、現在はnote.muに移転。

hachi8833の書いた記事

夏のTechRachoフェア2019

週刊Railsウォッチ

インフラ

ActiveSupport探訪シリーズ