はじめに
この記事は2023年度の振り返りです。
こちらの続きとなります。
問題を解いてる時の実話を元に、作成しております
勉強会内の小話
前回(has_many祭り)の続きです。
初学者達:これでどうだ!
class Author < ApplicationRecord
has_many :writes, foreign_key: 'user_id'
end
class Write < ApplicationRecord
belongs_to :author, foreign_key: 'user_id'
belongs_to :comic, foreign_key: 'book_id'
end
class Comic < ApplicationRecord
has_many :writes, foreign_key: 'book_id'
end
講師:確認してみよう
irb(main):139> author = Author.all.first
irb(main):140> author.writes
Author Load (0.4ms) SELECT `authors`.* FROM `authors` ORDER BY `authors`.`id` ASC LIMIT 1
Write Load (0.5ms) SELECT `writes`.* FROM `writes` WHERE `writes`.`user_id` = 1 /* loading for pp */ LIMIT 11
=>
[#<Write:0x00007f51f4a55990
id: 1,
book_id: 1,
user_id: 1,
created_at: Sat, 23 Dec 2023 02:56:25.572365000 UTC +00:00,
updated_at: Sat, 23 Dec 2023 02:56:25.572365000 UTC +00:00>,
#<Write:0x00007f51f4048fd8
id: 2,
book_id: 2,
user_id: 1,
created_at: Sat, 23 Dec 2023 02:56:25.580607000 UTC +00:00,
updated_at: Sat, 23 Dec 2023 02:56:25.580607000 UTC +00:00>]
irb(main):144> comic = Comic.all.first
irb(main):145> comic.writes
Comic Load (0.4ms) SELECT `comics`.* FROM `comics` ORDER BY `comics`.`id` ASC LIMIT 1
Write Load (0.5ms) SELECT `writes`.* FROM `writes` WHERE `writes`.`book_id` = 1 /* loading for pp */ LIMIT 11
=>
[#<Write:0x00007f51f41e2e48
id: 1,
book_id: 1,
user_id: 1,
created_at: Sat, 23 Dec 2023 02:56:25.572365000 UTC +00:00,
updated_at: Sat, 23 Dec 2023 02:56:25.572365000 UTC +00:00>]
irb(main):163> write = Write.all.first
Write Load (0.4ms) SELECT `writes`.* FROM `writes` ORDER BY `writes`.`id` ASC LIMIT 1
=>
#<Write:0x00007f51f41e3e88
...
irb(main):164> write.author
Author Load (0.4ms) SELECT `authors`.* FROM `authors` WHERE `authors`.`id` = 1 LIMIT 1
=>
#<Author:0x00007f51f4328c08
id: 1,
name: "岸本 斉史",
created_at: Sat, 23 Dec 2023 02:56:25.453889000 UTC +00:00,
updated_at: Sat, 23 Dec 2023 02:56:25.453889000 UTC +00:00>
irb(main):165> write.comic
Comic Load (0.4ms) SELECT `comics`.* FROM `comics` WHERE `comics`.`id` = 1 LIMIT 1
=>
#<Comic:0x00007f51f4c0e110
id: 1,
name: "NARUTO -ナルト-",
created_at: Sat, 23 Dec 2023 02:56:25.498858000 UTC +00:00,
updated_at: Sat, 23 Dec 2023 02:56:25.498858000 UTC +00:00>
講師:うん。あってそうだな。
講師:一応言っとくと、公式のhas_manyの一つ目の引数が関連モデル名となってるが、完全にモデル名とは言いづらいケースもある。
講師:この作ったhas_manyを伝えるときに名称がないと伝えづらい時があるので、個人的にはリレーション名と呼んでたりする。なので、この勉強会ではリレーション名で通させてもらうよ。
初学者達:一部腑に落ちないけど、リレーション名ですね。わかりました!
講師:じゃぁ、引き続きjoinで解いてみよう
初学者達:で、active recordのjoinって、どうすんですか?
講師:知らないなら、調べるべし
初学者達:あ、はい。
初学者達:こちらの記事のこの部分を流用すれば、こんな感じじゃないですか?
author = Author.where(name: '冨樫 義博')
p Comic.joins(:writes).where(writes: { user_id: author })
講師:少し確認してみよう
SELECT `comics`.*
FROM `comics`
INNER JOIN `writes` ON `writes`.`book_id` = `comics`.`id`
WHERE `writes`.`user_id` IN (
SELECT `authors`.`id`
FROM `authors`
WHERE `authors`.`name` = '冨樫 義博'
)
講師:1クエリで、望むレコードが返る物ができたっぽいね
初学者達:お!一発合格ですか!次行きましょう次!
講師:いやいや。次の別の解き方をやってみよう
初学者達:まだあるんですか??
講師:まだまだある。例えば、今サブクエリを使ってるけど、使わない方法もあるよ
講師:例えばこんな感じもできる
p Comic.joins(writes: :author).where(author: { name: '冨樫 義博' })
SELECT `comics`.*
FROM `comics`
INNER JOIN `writes` ON `writes`.`book_id` = `comics`.`id`
INNER JOIN `authors` `author` ON `author`.`id` = `writes`.`user_id`
WHERE `author`.`name` = '冨樫 義博'
初学者達:おー!SQLもすっきり!
講師:じゃぁ、次の別の解き方をやってみよう。別の解き方というかブラッシュアップに近いと思うけど
初学者達:えーーーー。まだあるんですかーーー
次回へ続く
さいごに
今回は、joinsを使った初回の話でした。
区切りがいいのでここまでにします。