2020-04-11
【Rails】ActiveRecordでJOIN先のテーブルのカラムで絞り込む
#includes や #joins でテーブルをJOINしたときに、軸となるテーブルではなくJOIN先のテーブルのカラムで絞り込む方法について。
例として、デッキとカードという2つのモデルがありデッキがカードをN個持つ関係にあるとする。
app/models/deck.rb
class Deck < ApplicationRecord
has_many :cards
end
app/models/card.rb
class Card < ApplicationRecord
belongs_to :deck
end
※ 検証環境は以下の通り
- rails 6.0.1
- ruby 2.6.5
joins × merge
#joins
と #merge
を組み合わせる。#includes
の場合は使えない。
Deck.joins(:cards).merge(Card.where(id: 1))
# => SELECT "decks".* FROM "decks" INNER JOIN "cards" ON "cards"."deck_id" = "decks"."id" WHERE "cards"."id" = $1 [["id", 1]]
whereメソッドにテーブル名をkeyとして渡す
#joins
の場合はINNER JOINとなり、#includes
の場合はLEFT OUTER JOINになる。
Deck.joins(:cards).where(cards: { id: 1 })
# => SELECT "decks".* FROM "decks" INNER JOIN "cards" ON "cards"."deck_id" = "decks"."id" WHERE "cards"."id" = $1 [["id", 1]]
Deck.includes(:cards).where(cards: { id: 1 })
# => SELECT "decks"."id" AS t0_r0, ...(省略) FROM "decks" LEFT OUTER JOIN "cards" ON "cards"."deck_id" = "decks"."id" WHERE "cards"."id" = $1 [["id", 1]]
文字列でJOIN先のテーブルを指定する
Deck.joins(:cards).where('cards.id = ?', 1)
# => SELECT "decks".* FROM "decks" INNER JOIN "cards" ON "cards"."deck_id" = "decks"."id" WHERE (cards.id = 1)
#includes
でこの書き方をする場合は #references と組み合わせないと動かない
Deck.includes(:cards).where('cards.id = ?', 1).references(:cards)
# => SELECT "decks"."id" AS t0_r0, ...(省略) FROM "decks" LEFT OUTER JOIN "cards" ON "cards"."deck_id" = "decks"."id" WHERE (cards.id = 1)
<< 前の記事AWSアカウントとIAMユーザ
次の記事 >>git resetをちゃんと理解する