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】has_manyに条件付きスコープを設定して関連を絞り込む

Last updated at Posted at 2025-09-18

はじめに

has_manyに条件付きスコープを設定すると、関連を呼び出すだけで自動的に絞り込みがかかります。
使いどころが分かりづらかったので、実際に実装して学んだことをまとめます。

定義例

Companyモデル

class Company < ApplicationRecord
  has_many :employees

  has_many :engineers, -> { where role: ROLE_ENGINEER }, class_name: "Employee"
  has_many :designers, -> { where role: ROLE_DESIGNER }, class_name: "Employee"
  has_many :interns, -> { where role: ROLE_INTERN }, class_name: "Employee"
end
  • has_many :engineers, -> { where role: ROLE_ENGINEER }, class_name: "Employee" : engineersの中から、roleROLE_NEGINERRSのものだけを絞り込む
    • ->{where ...} : スコープ付き関連。関連を呼び出し時に自動で条件が付く
    • class_name: "Employee": 関連名(engineers)とクラス名が一致しないため明示的に指定

Employeeモデル

class Employee < ApplicationRecord
  belongs_to :company

# roleカラムの値
  ROLE_ENGINEER = 1
  ROLE_DESIGNER = 2
  ROLE_INTERN   = 3
end

呼び出し例

company.engineers
company.employees.where(role: ROLE_ENGINEER)

# 両方とも以下のようなSQLが実行され、同じ結果となる
SELECT `employees`.* FROM `employees`
WHERE `employees`.`compay_id` = 1 
AND `employees`.`role` = 1

メリット

  • 可読性が高い
    company.engineersのように自然な形で呼び出せる
  • ActiveRecordの機能がそのまま使える
  • 再利用しやすい
    条件をモデルに集約できる

デメリット

  • 関連が増えるとモデル定義が肥大化する
  • 条件が複雑になると可読性が落ちる

おわりに

ドメインとして意味のある分類は、モデルのアソシエーションとして定義すると再利用性や可読性が高まります。一方で、一時的な絞り込みやビュー専用の条件など、ドメインに直接関係しないものはスコープやヘルパーで対応した方が使いやすい場合があるので見極めが必要になりそうです。

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?