# preload では 自分からの検索は可能
users = User.where(id: [1,2,3,4,5]).preload(:books)
# preload では 関連先のテーブルからの検索は不可能
users = User.preload(:books).where(books: { name: "Alice Wonder Land" }).first
# ActiveRecord::StatementInvalid: Mysql2::Error: Unknown column ...
# preload + joins で関連先のテーブルからの検索が可能だが、 join の作用で 関連先テーブルの数だけ返ってくる結果数も多くなる
# 同じUserのインスタンスが大量に返ってきたり
# merge でも where でも書けるが、どちらでも挙動は変わらないっぽい?
users = User.joins(:books).preload(:books).where(books: { name: "Alice Wonder Land" })
users = User.joins(:books).preload(:books).merge(Book.where(name: "Alice Wonder Land" ))
# preload + joins
# uniq すれば User もユニークになるが、なんだか無理やりな気もする
users = User.joins(:books).preload(:books).merge(Book.where(name: "Alice Wonder Land" )).uniq
# eager_load では関連先テーブルからも検索も可能
users = User.eager_load(:books).where(books: { name: "Alice Wonder Land" })
# includes は preload と eager_load のどちらかを自動で切り替えてくれるので、関連先テーブルから検索しようとすると、eager_load と同じクエリ、同じ挙動になる
users = User.includes(:books).where(books: { name: "Alice Wonder Land" })
ヒント
.to_sql
メソッドでクエリの中身を見てみたり、そのSQLを直接 DB に発行して、返ってくるDBの結果を見てみよう。
参考
ActiveRecord ~ 複数テーブルにまたがる検索(preload, eager_load, include, joins) - Qiita
Original by Github issue
チャットメンバー募集
何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。