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

概要 原著者の許諾を得て翻訳・公開いたします。 英語記事: Ruby on Rails - make a if condition more simple with a scope 原文公開日: 2018/02/12 著者: Paweł Dąbrowsk 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のクラスメソッドがリファクタリングに抵抗する理由(翻訳)