勉強会での小話4

# はじめに

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

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

https://qiita.com/youfuku/items/ccdafe5ccf1abd2d9fb7

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

# 勉強会内の小話
前回（has_many祭り）の続きです。

初学者達：これでどうだ！

```ruby:app/models/author.rb
class Author < ApplicationRecord
  has_many :writes, foreign_key: 'user_id'
end
```

```ruby:app/models/write.rb
class Write < ApplicationRecord
  belongs_to :author, foreign_key: 'user_id'
  belongs_to :comic, foreign_key: 'book_id'
end
```

```ruby:app/models/comic.rb
class Comic < ApplicationRecord
  has_many :writes, foreign_key: 'book_id'
end
```

講師：確認してみよう
```ruby
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>]
```

```ruby
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>]
```

```ruby
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](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3632357/08ebe221-ce64-ad1b-8aaf-e446b848ecbc.png)

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

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

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

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

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

初学者達：あ、はい。

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

https://www.sejuku.net/blog/26522

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3632357/93ae92d0-b89f-3e3f-1283-7e80bbb2cc2f.png)

```ruby
author = Author.where(name: '冨樫 義博')
p Comic.joins(:writes).where(writes: { user_id: author })
```

講師：少し確認してみよう
```sql
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クエリで、望むレコードが返る物ができたっぽいね

初学者達：お！一発合格ですか！次行きましょう次！

講師：いやいや。次の別の解き方をやってみよう

初学者達：まだあるんですか？？

講師：まだまだある。例えば、今サブクエリを使ってるけど、使わない方法もあるよ

講師：例えばこんな感じもできる
```ruby
p Comic.joins(writes: :author).where(author: { name: '冨樫 義博' })
```
```sql
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を使った初回の話でした。
区切りがいいのでここまでにします。