【Rails】where.associatedで関連付けられているレコードを簡単に取得する方法

はじめに

こんにちは株式会社のナオキです!
以前、where.missingについて詳しく解説したブログを書きました。
簡単に説明すると、where.missingは関連付けられたデータが存在しないレコードのみを取得するメソッドです。

今回はwhere.missingとは逆で、関連付けられたデータが存在するレコードのみを取得するメソッドwhere.associatedについて解説していきます!

この記事では以下の内容について取り上げています。

  • where.associatedの概要
  • where.associatedの基本的な使用方法
  • SQLについて

対象読者

  • Rails初学者の方
  • Railsで開発を行っている方

where.associatedの概要

where.associatedは、Rails7.1で導入されたクエリメソッドです。
クエリメソッドとは、データベースからデータを検索、操作するためのメソッドです。
where.associatedメソッドは関連付けられたデータが存在するレコードを絞り込み取得します!

例えばUser(ユーザー)モデルとPost(投稿)モデルが以下のように1対多で関連付けられているとします。

class User < ApplicationRecord
  has_many :posts
end
class Post < ApplicationRecord
  belongs_to :user
end

このような場合、ユーザーは複数の投稿を持つこともできますし、持たない場合もあります。
このときwhere.associatedを使用することで投稿を持つユーザーのみを全て取得することが出来ます!

where.associatedの基本的な使用方法

基本的な使用方法として「投稿をもつユーザー」を取得する方法は以下のようになります。

User.where.associated(:posts)

この記述で投稿を持つ全てのユーザーのレコードを取得することができます。

ユーザーが投稿の他に、コメント(Comment)モデルと1対多で関連付いているとします。
投稿とコメントを持つユーザーを取得したいときも、以下のように簡単に記述することが出来ます。

User.where.associated(:posts, :comments)

SQLについて

where.associatedは、内部的にINNER JOINを用いたSQLを生成します。

User.where.associated(:posts)

上記のように記述した場合、生成されるSQLは以下のようになります。

SELECT "users".*
FROM "users"
INNER JOIN "posts" ON "posts"."user_id" = "users"."id"

INNER JOIN "posts"usersテーブルとpostsテーブルを結合します。
INNER JOIN は、結合条件に一致するデータのみを結果として返します。この場合、usersテーブルとpostsテーブルを結合し、ON "posts"."user_id" = "users"."id"の条件に一致するレコードだけが対象になります。
そのため、投稿をもつユーザーのみを取得することが出来るのです!

さいごに

今回は、Railsのwhere.associatedクエリメソッドについての解説をしました。
このメソッドを使用することで、関連付けられたデータの絞り込みが簡単に記述でき可読性があがります。
また以前紹介したwhere.missingメソッドと使い分けることで、関連データの有無による絞り込みが簡単に行えます。
ぜひ開発する際にwhere.associatedを使用してみてください!