Ruby
 Computer >> コンピューター >  >> プログラミング >> Ruby

【Rails入門】scopeの使い方を徹底解説!基本構文から引数付きスコープ、クラスメソッドとの違いまで

Railsにおける「スコープ(scope)」とは何か?そしてなぜ便利なのでしょうか?

答えはこうです。

スコープとは、scopeメソッドを使ってモデル内に定義するカスタムクエリのことです。よく使う検索条件に名前をつけて再利用できるようにする仕組みと言えます。

すべてのスコープは2つの引数を受け取ります。

  1. 名前:コード内でこのスコープを呼び出す際に使用します。
  2. ラムダ(lambda):実際のクエリ処理を実装します。

具体的には次のように書きます。

class Fruit < ApplicationRecord
  scope :with_juice, -> { where("juice > 0") }
end

スコープを呼び出すと、戻り値としてActiveRecord::Relationオブジェクトが返されます。

つまり、スコープはチェーン(連結)して組み合わせることができるのです!

例:

Fruit.with_juice.with_round_shape.first(3)

それでは、Railsスコープについて学ぶべきことはまだまだあります。さらに詳しく見ていきましょう。

スコープはいつ使うべき?

スコープは確かに便利ですが、実際にはどんな場面で使うべきなのでしょうか?

具体例を見てみましょう。

def index
  @books = Book.where("LENGTH(title) > 20")
end

これは、タイトルが20文字より長い本だけを表示したいindexコントローラアクションです。

これ自体は問題ありません。

しかし、同じクエリを他の場所でも使いたくなったらどうでしょう?コードが重複してしまいます。

重複したコードはプロジェクトの保守性を下げる原因になります。

そこで、このクエリをスコープとして切り出してみましょう。

次のように書きます。

class Book < ApplicationRecord
  scope :with_long_title, -> { where("LENGTH(title) > 20") }
end

すると、コントローラのアクションはこのようになります。

def index
  @books = Book.with_long_title
end

すっきりしましたね!

引数付きのスコープの使い方

スコープに変数を導入すれば、より柔軟なクエリを作成できます。

書き方はこちら。

class Book < ApplicationRecord
  scope :with_long_title, ->(length) { where("LENGTH(title) > ?", length) }
end

疑問符(?)はプレースホルダーで、実行時にlengthの値に置き換えられます。この書き方によりSQLインジェクションを防ぎ、コードの安全性が高まります。

デフォルト値を設定したい場合は、次のように書きます。

class Book < ApplicationRecord
  scope :with_long_title, ->(length = 20) { where("LENGTH(title) > ?", length) }
end

ぜひ実際に試してみてください!

スコープとクラスメソッドの違い

実は、スコープには魔法のような特別な仕組みがあるわけではありません。

スコープは単なるメソッドです。

実際のところ…クラスメソッドでも同じことが実現できます!

例えばこんな感じです。

class Fruit < ApplicationRecord
  def self.with_juice
    where("juice > 0")
  end
end

では、なぜクラスメソッドではなくスコープを使うのでしょうか?設計上のメリットがあります。

その理由は以下の通りです。

  • シンタックスのおかげでコードがより簡潔になる
  • スコープは「クエリ定義」というたった一つの目的のために使われるため、見た瞬間に役割がわかる
  • 他のメソッドと混ざらないため、コードの中で見つけやすい

機能面での唯一の違いは、スコープは必ずActiveRecord::Relationを返すことが保証されている点です。クラスメソッドにはこの保証がありません。

このおかげで、スコープの結果が空だった場合でもエラーを回避しやすくなります。例えば、nilに対してメソッドチェーンを続けてしまうようなバグを防げます。

default_scopeは使うべきではない

デフォルトスコープとは、モデルに対して自動的に適用されるスコープのことです。

例:

class Post < ApplicationRecord
  default_scope { where(published: true) }
end

一見すると非常に魅力的に感じますよね。

しかし、デフォルトスコープは多くの場合誤った選択です。定義したことを忘れてしまい、予期しない挙動や奇妙なエラーに遭遇し、貴重なデバッグ時間を浪費することになりかねません。

とはいえ…

どうしてもデフォルトスコープが適用されたモデルを扱う必要がある場合は、unscopedメソッドを使えば、現在適用されているすべてのスコープを無効化できます。

まとめ

お疲れさまでした!この記事を読むことで、Railsスコープを最も効果的に活用する方法を学べました。

学んだ内容を忘れないように、ぜひ実際のプロジェクトで試してみてください。

最後までお読みいただきありがとうございました。🙂

  1. RubyのStructとOpenStructの使い方を徹底解説!値オブジェクトを簡単に作る方法

    Rubyには、関連する属性をまとめて保持する「値オブジェクト」を手軽に作れるStructという組み込みクラスが用意されています。本記事では、Structの基本的な使い方から注意点、そしてOpenStructとの違いまで詳しく解説します。 そもそもStructとは何か? StructはRubyに組み込まれたクラスで、新しいクラスを動的に生成し、値オブジェクト(Value Object)を作成するために使われます。値オブジェクトとは、関連性のある複数の属性をひとまとめにして扱うためのオブジェクトです。 具体例を挙げてみましょう。 2つの座標(xとy)を持つPointというデータを表したい場合、この

  2. RailsアプリでTwitterログインを実装する方法:OmniAuth-Twitter完全ガイド

    このチュートリアルでは、RailsアプリケーションのユーザーがTwitterアカウントを使ってログインできるようにする方法を解説します。OAuthなどのツールのおかげで、この実装はとても簡単に行えるようになりました。 今回は、OmniAuth用のTwitterストラテジーを含む「OmniAuth-Twitter」を使用します。 それでは始めましょう! はじめに:プロジェクトの準備 まずはRailsアプリケーションを生成します。ターミナルで以下のコマンドを実行してください。 rails new Tuts-Social -T 次にGemfileを開き、bootstrap gemを追加します。