0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

RailsのScope vs クラスメソッド:返り値とSQLクエリの違いを徹底解説

Last updated at Posted at 2025-03-01

Scopeについて

モデルには、Scopeというものを定義できる。
Scopeとは、よく利用する検索条件に名前をつけて、ひとまとめにしたもの。
高価なワインだけを取得するためのScope、costlyを定義↓

class Wine < ApplicationRecord
    scope :costly, -> { where("price > ?", 5000) }
end
Wine.costly

↑この記述だけで、↓と対価となります。

Wine.where("price > ?", 5000)

メリットは2つ
1.繰り返し利用するクエリの再利用性が上がる
2.クエリに名前をつけることで、可読性が向上

クエリ(Query)とは?

クエリとは、データベースに対して「データを取得したり、追加・更新・削除するための指示(命令)」のこと。
今回の例だと、データベースの winesテーブルから価格が 5000 円以上のワインを取得したい場合、SQLだと次のようなクエリになります。

SELECT "wines".* FROM "wines" WHERE (price > 5000) 

Rails では、ActiveRecord を使ってこのクエリを Ruby のコードとして表現できる。
Scopeを使えば、以下のコードだけで表現できます。

Wine.costly

データベースとアプリケーションの橋渡しをするのがクエリの役割で、アプリケーションはクエリを使ってデータを取得したり、更新したりして、それを画面に表示する。

Scopeとクラスメソッドの違い

大きく分けて3つあります。

1.返り値
2.生成されるSQLクエリ
3.チェーン(連結)できるかどうか

Scope

Scopeを利用してWine.costlyを実行すると
必ずActiveRecord::Relationを返します。
sqlクエリにはLIMIT が付かないため、条件に合致するすべてのレコードが取得できます。

SELECT "wines".* FROM "wines" WHERE (price > 5000)

必ずActiveRecord::Relationを返すため、チェーンしてさらに条件を追記できる

Wine.costly.where("name LIKE ?", "%Chateau%")

発行されるSQLクエリ↓

SELECT "wines".* FROM "wines" WHERE (price > 5000) AND (name LIKE '%Chateau%')

クラスメソッド

def self.find_by_price(price)
  find_by(price: price)
end

find_byを利用するため、返り値は単一のレコードか、nilになります。(レコードが見つからなければnil)そのため、チェーンで他の条件を追加することはできません。

Wine.find_by_price(5000) 

上記を実行すると、
発行されるSQLクエリ↓

SELECT "wines".* FROM "wines" WHERE "wines"."price" = 5000 LIMIT 1

LIMIT 1 が自動的に付加されるため、最初の1件だけが返されるようになっています。

まとめ

Scopeは複数のレコードを対象に条件をチェーンで追加でき、SQLクエリもその条件が全て反映されます。結果がnilとなった場合も該当Scopeの検索条件を除外したクエリを発行し、必ずActiveRecord::Relationを返すという動作をします。

一方、クラスメソッドは単一レコードの取得に特化していて、SQLクエリには自動的に LIMIT 1 が付与され、チェーンもできません。

Scopeで定義する場合とクラスメソッドで定義する場合はこのような違いがあるため、nilを返す必要がある場合はクラスメソッドとして定義する必要があります。

参考文献

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?