3
0

勉強会での小話4

Posted at

はじめに

この記事は2023年度の振り返りです。

こちらの続きとなります。

問題を解いてる時の実話を元に、作成しております

勉強会内の小話

前回(has_many祭り)の続きです。

初学者達:これでどうだ!

app/models/author.rb
class Author < ApplicationRecord
  has_many :writes, foreign_key: 'user_id'
end
app/models/write.rb
class Write < ApplicationRecord
  belongs_to :author, foreign_key: 'user_id'
  belongs_to :comic, foreign_key: 'book_id'
end
app/models/comic.rb
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の一つ目の引数が関連モデル名となってるが、完全にモデル名とは言いづらいケースもある。
image.png

講師:この作ったhas_manyを伝えるときに名称がないと伝えづらい時があるので、個人的にはリレーション名と呼んでたりする。なので、この勉強会ではリレーション名で通させてもらうよ。

初学者達:一部腑に落ちないけど、リレーション名ですね。わかりました!

講師:じゃぁ、引き続きjoinで解いてみよう

初学者達:で、active recordのjoinって、どうすんですか?

講師:知らないなら、調べるべし

初学者達:あ、はい。

初学者達:こちらの記事のこの部分を流用すれば、こんな感じじゃないですか?

image.png

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を使った初回の話でした。
区切りがいいのでここまでにします。

3
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
3
0