【Rails】has_manyをhas_oneに変えた時の挙動

has_manyで複数のレコードが紐づいている状態で、has_oneに変えるとどのレコードが紐づくのかふと気になったので試してみた。
言い換えると、`has_many`関係で`article.comments`が複数取れる状況だった時に、`has_one`に変更して`article.comment`を実行すると、どのレコードを取ってくるのかを見てみた。
## 結論
**created_at, updated_atの値に関係なく、idの一番若いレコードと紐づく**

一番新しいレコードを取ってくるのかなぁと思ったらそうではなかった。
上の結論に至るまでの検証を下にまとめていく。

## 前提

ArticleモデルとCommentモデルを用意し、Article `has_many` Commentsの関係をとるとする。

```ruby:article.rb
class Article < ApplicationRecord
  has_many :comments
  # has_one :comment #検証用
end
```

```ruby:comment.rb
class Comment < ApplicationRecord
  belongs_to :article
end
```
用意したレコードは**article1個**、**comment3個**。commentは全てarticleに紐づいてるものとする。

```ruby:article
#<Article:0x00007f979bad9f00
 id: 1,
 title: "title1",
 created_at: Tue, 03 Dec 2019 04:54:13 UTC +00:00,
 updated_at: Tue, 03 Dec 2019 04:54:13 UTC +00:00>
```

```ruby:comment
[#<Comment:0x00007f9798e79f28
  id: 1,
  content: "comment1",
  article_id: 1,
  created_at: Tue, 03 Dec 2019 04:55:15 UTC +00:00,
  updated_at: Tue, 03 Dec 2019 04:55:15 UTC +00:00>,
 #<Comment:0x00007f9798e79d98
  id: 2,
  content: "comment2",
  article_id: 1,
  created_at: Tue, 03 Dec 2019 04:55:23 UTC +00:00,
  updated_at: Tue, 03 Dec 2019 04:55:23 UTC +00:00>,
 #<Comment:0x00007f9798e79c08
  id: 3,
  content: "comment3",
  article_id: 1,
  created_at: Tue, 03 Dec 2019 04:55:26 UTC +00:00,
  updated_at: Tue, 03 Dec 2019 04:55:26 UTC +00:00>]
```

## 検証1 上記条件でhas_many => has_oneに変更
上記の状態で article.rb の `has_many` をコメントアウトし、 `has_one`に変更
`Article.first.comment`実行

```ruby
[1] pry(main)> Article.first.comment
```

### 結果
id = 1のcomment

```ruby:result
=> #<Comment:0x00007f979b488638
 id: 1,
 content: "comment1",
 article_id: 1,
 created_at: Tue, 03 Dec 2019 04:55:15 UTC +00:00,
 updated_at: Tue, 03 Dec 2019 04:55:15 UTC +00:00>
```

=> 一番若いidを取ってくる

結論の通り。だけどこれだけではupdated_atとcreated_atの影響の可能性も捨てきれないので、もうちょい掘り下げる。

##検証2 update_atの値を変える
id=1のcommentを**アップデート**し、`updated_at`を他二つより最近のものにする
`has_one`に変更し、`Article.first.comment`実行

```ruby
[1] pry(main)> Comment.first.update_attributes(content: "comment1A")
[2] pry(main)> Article.first.comment
```


### 結果
id = 1のcomment

```ruby:result
=> #<Comment:0x00007f979b675568
 id: 1,
 content: "comment1A",
 article_id: 1,
 created_at: Tue, 03 Dec 2019 04:55:15 UTC +00:00,
 updated_at: Tue, 03 Dec 2019 04:59:09 UTC +00:00>
```

=> **updated_atの値に関係なく**一番若いidを取ってくる
updated_atの値を見てわかる通り。

## 検証3 id=1 のCommentレコードを削除
id=1のcommentを**削除**
`has_one`に変更し、同様に実行

```ruby
[1] pry(main)> Comment.first.delete
[2] pry(main)> Article.first.comment
```

### 結果
id = 2のcomment

```ruby:result
=> #<Comment:0x00007f979bbe3540
 id: 2,
 content: "comment2",
 article_id: 1,
 created_at: Tue, 03 Dec 2019 04:55:23 UTC +00:00,
 updated_at: Tue, 03 Dec 2019 04:55:23 UTC +00:00>
```

=> 存在しているレコードの中で一番若いidを取ってくる
commentのidが2と3しかない状態なのでこのようになる

## 検証4 再び id=1 のCommentレコードを追加
検証3を終えた状態 (id=1のcommentを消した状態) で
id=1のcommentを再び**create**。articleに紐づける
`has_one`に変更し、同様に実行

```ruby
[1] pry(main)> Comment.create(id:1, content:"comment1", article_id:1)
[2] pry(main)> Article.first.comment
```

### 結果
**id = 1のcomment**

```ruby:result
=> #<Comment:0x00007f979b88a678
 id: 1,
 content: "comment1",
 article_id: 1,
 created_at: Tue, 03 Dec 2019 05:05:59 UTC +00:00,
 updated_at: Tue, 03 Dec 2019 05:05:59 UTC +00:00>
```
=> **created_atの値に関係なく**一番若いidを取ってくる
今までは**"idが一番若い = created_atの値が一番古い"**が成り立ってたたため、これでcreated_atの値が関係ないことがわかった。
一度消したのでid=2をとってくるかと思いきやid=1だった。

## 終わりに
結論の通り、has_manyからhas_oneに変更した場合、idの一番若いものを取ってくることがわかった。直感的には一番新しいレコードを取ってきそうな気はするけど、そうではないっぽいので気をつけたい。検証不足、間違い等ありましたらコメントお願いしますm(_ _)m