[Rails]has_oneやbelongs_toをリロード！削除されたときの挙動がreload_associationとreloadで違うので注意！

ActiveRecordのアソシエーションは1度取得するとキャッシュしてくれるため、2度目からはSQLが発行されません。
この機能はとても便利なのですが、たまに最新の情報にリロードしたいときがあります。

例えば下記のようにuser.profile.addressが別で更新された場合です。

```irb
irb(main):001:0> user = User.first

# profileは初回アクセスなので、SQLが発行される
irb(main):003:0> user.profile.address
  Profile Load (0.9ms)  SELECT `profiles`.* FROM `profiles` WHERE `profiles`.`user_id` = 2 LIMIT 1
=> "住所だよ"

# profileはキャッシュしているのでSQLは発行されない
irb(main):004:0> user.profile.address
=> "住所だよ"

# 別プロセスでprofile.addressを更新
irb(main):005:0> Profile.find(1).update!(address: '住所だよ!!!!!')
  Profile Load (1.6ms)  SELECT `profiles`.* FROM `profiles` WHERE `profiles`.`id` = 1 LIMIT 1
  TRANSACTION (0.7ms)  BEGIN
  User Load (0.9ms)  SELECT `users`.* FROM `users` WHERE `users`.`id` = 2 LIMIT 1
  Profile Update (1.1ms)  UPDATE `profiles` SET `profiles`.`address` = '住所だよ!!!!!', `profiles`.`updated_at` = '2021-10-29 07:44:20.414663' WHERE `profiles`.`id` = 1
  TRANSACTION (3.5ms)  COMMIT
=> true

# キャッシュから取得するため、更新されていない
irb(main):006:0> user.profile.address
=> "住所だよ"
```


そんなときに2つのやり方があります。

1つ目はActiveRecordの`reload`を使います。

https://api.rubyonrails.org/v6.1.4/classes/ActiveRecord/Persistence.html#method-i-reload

reloadを使うと、下記のようにSQLが発行されて最新の情報に更新されます。

```irb
irb(main):007:0> user.profile.address
=> "住所だよ"
irb(main):008:0> user.profile.reload
  Profile Load (0.9ms)  SELECT `profiles`.* FROM `profiles` WHERE `profiles`.`id` = 1 LIMIT 1
=> #<Profile:0x000055ba8153a7a0 id: 1, user_id: 2, address: "住所だよ!!!!!", created_at: Wed, 20 Oct 2021 02:12:12.898532000 UTC +00:00, updated_at: Fri, 29 Oct 2021 07:44:20.414663000 UTC +00:00>
irb(main):009:0> user.profile.address
=> "住所だよ!!!!!"
```

2つ目はアソシエーションを設定したら自動生成される`reload_#{アソシエーション名}`です。
has_oneとbelongs_toのどちらにも同様に生成されます。

https://railsguides.jp/association_basics.html#belongs-to%E3%81%A7%E8%BF%BD%E5%8A%A0%E3%81%95%E3%82%8C%E3%82%8B%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89

```irb
irb(main):013:0> user.profile.address
=> "住所だよ"
irb(main):014:0> user.reload_profile
  Profile Load (0.9ms)  SELECT `profiles`.* FROM `profiles` WHERE `profiles`.`user_id` = 2 LIMIT 1
=> #<Profile:0x000055ba8206ec48 id: 1, user_id: 2, address: "住所だよ!!!!!", created_at: Wed, 20 Oct 2021 02:12:12.898532000 UTC +00:00, updated_at: Fri, 29 Oct 2021 08:04:07.284792000 UTC +00:00>
irb(main):015:0> user.profile.address
=> "住所だよ!!!!!"
```

上記の通り、データが存在しているときはどちらを使っても同じように再取得されるのですが、削除されていた場合は挙動が違うので注意が必要です。

`reload`を使った場合

```irb
irb(main):018:0> Profile.find(1).destroy
  Profile Load (1.1ms)  SELECT `profiles`.* FROM `profiles` WHERE `profiles`.`id` = 1 LIMIT 1
  Profile Destroy (1.1ms)  DELETE FROM `profiles` WHERE `profiles`.`id` = 1

irb(main):019:0> user.profile.reload
  Profile Load (0.8ms)  SELECT `profiles`.* FROM `profiles` WHERE `profiles`.`id` = 1 LIMIT 1
/usr/local/bundle/gems/activerecord-6.1.4.1/lib/active_record/relation/finder_methods.rb:357:in `raise_record_not_found_exception!': Couldn't find Profile with 'id'=1 (ActiveRecord::RecordNotFound)
```

`reload_#{アソシエーション名}`を使った場合

```irb
irb(main):003:0> Profile.find(1).destroy
  Profile Load (0.7ms)  SELECT `profiles`.* FROM `profiles` WHERE `profiles`.`id` = 1 LIMIT 1
  Profile Destroy (0.9ms)  DELETE FROM `profiles` WHERE `profiles`.`id` = 1

irb(main):004:0> user.reload_profile
  Profile Load (0.8ms)  SELECT `profiles`.* FROM `profiles` WHERE `profiles`.`user_id` = 2 LIMIT 1
=> nil
```

`reload`を使った場合、データが見つからないと`ActiveRecord::RecordNotFound`が発生します。
一方、`reload_#{アソシエーション名}`を使った場合はデータが見つからないとnilになります。

削除される可能性があるデータを扱う場合はご注意ください！！