Rails tips: スコープを用いてif条件をシンプルにする(翻訳)

概要

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

Rails tips: スコープを用いてif条件をシンプルにする(翻訳)

シンプルなスコープを使ってif条件を簡単にできる状況はとてもよく見かけます。サンプルのクラスでやり方をご覧にいれます。

class User < ActiveRecord::Base
  has_many :posts
end
class NotificationService
  def initialize(company:)
    @company = company
  end

  def notify_user(email:)
    user = User.find_by(email: email)

    if user.present? && user.posts.any?
      Mailer.new_posts_reminder(user.id).deliver
    end
  end

  private
  attr_reader :company
end

Userモデルがあって、has_many :postsによって各ユーザーが複数のpostsを持つことができます。NotificationServiceは、ユーザーが新しく投稿を作成したときに簡単なメールメッセージでユーザーにリマインダーを送信するのに用いられます。

ここではusers.posts.any?をチェックする必要はありません。というのも、これはデータベースレベルで行われるからです。postsを持つユーザー向けのスコープを作成してみましょう。

class User < ActiveRecord::Base
  has_many :posts

  scope :with_posts, -> { joins(:posts) }
end

スコープはクラスメソッドとして定義することも可能であり、どちらにするかはあなた次第です。どちらにすべきかよくわからない方は、モデルのクエリをカプセル化する2つの方法をご覧ください。ともあれ、これで更新されたデータベースクエリが使えるようになり、条件をリファクタリングできるようになりました。

class NotificationService
  def initialize(company:)
    @company = company
  end

  def notify_user(email:)
    user = User.with_posts.find_by(email: email)

    user && Mailer.new_posts_reminder(user.id).deliver
  end

  private
  attr_reader :company
end

コードがぐっとシンプルかつ短くなりました。しかもクエリが自らの挙動を語るようになりました。ほんのささやかなリファクタリングですが、この違いは大きいものです。この方法は、今後ユーザーがpostsを持つかどうかを決定する責務を持つコードを変更するときにも役立つのが嬉しい点です。変更前の方法では、ユーザーがpostsを持つかどうかをあちこちでチェックしなければなりませんでしたが、変更後の新しい方法ならUserモデルのスコープを変更するだけで済みます。

上の変更は、belongs_to関連付けのクエリのリファクタリングにも関連します。


Railsでお困りの方にお知らせ

知りたいことがありましたら、twitter または連絡用フォームにてお気軽にお問い合わせください。

お知らせ: RSpec & TDDの電子書籍を無料でダウンロード

もっと稼ぎたい方や会社をさらに発展させたい方へ: テスティングのスキルの重要性にお気づきでしょうか?テストを正しく書き始めることが、唯一のファーストステップです。無料でダウンロードいただける私の書籍『RSpec & Test Driven Developmentの無料ebook』をどうぞお役立てください。

関連記事

Rails: テストのリファクタリングでアプリ設計を改良する(翻訳)

Rubyのクラスメソッドがリファクタリングに抵抗する理由(翻訳)

Ruby on RailsによるWEBシステム開発、Android/iPhoneアプリ開発、電子書籍配信のことならお任せください この記事を書いた人と働こう! Ruby on Rails の開発なら実績豊富なBPS

この記事の著者

hachi8833

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

hachi8833の書いた記事

週刊Railsウォッチ

インフラ

BigBinary記事より

ActiveSupport探訪シリーズ