環境
- Rails 7.0.0
- Ruby 2.7.5
- MySQL 5.7
前提
- user.rb
class User < ApplicationRecord
  has_one :item, dependent: :destroy
end
- item.rb
class Item < ApplicationRecord
  belongs_to :user
end
解説
ActiveRecordでhas_one関連付けを利用すると、以下のメソッドが追加される。
- build_association(attributes = {})
このメソッドはオブジェクトを作成するだけでレコードを保存・更新・削除しないように見えるが、特定の状況ではレコードが削除される。
準備
userとそれに紐づくitemを作成する。
$ irb(main):001:0> user = User.create!
  TRANSACTION (0.3ms)  BEGIN
  User Create (0.7ms)  INSERT INTO `users` (`name`, `created_at`, `updated_at`) VALUES (NULL, '2021-12-22 13:15:26.923535', '2021-12-22 13:15:26.923535')
  TRANSACTION (1.6ms)  COMMIT
=> #<User:0x00005555bc407cb8 id: 5, name: nil, created_at: Wed, 22 Dec 2021 13:15:26.923535000 UTC +00:00, updated_at: Wed, 22 Dec 2021 13:15:26.923535000 UTC +00:00>
$ irb(main):002:0> user.create_item
  TRANSACTION (0.7ms)  BEGIN
  Item Create (0.8ms)  INSERT INTO `items` (`user_id`, `name`, `created_at`, `updated_at`) VALUES (5, NULL, '2021-12-22 13:15:53.782148', '2021-12-22 13:15:53.782148')
  TRANSACTION (1.6ms)  COMMIT
  Item Load (1.2ms)  SELECT `items`.* FROM `items` WHERE `items`.`user_id` = 5 LIMIT 1
=> #<Item:0x00007f857080e768 id: 12, user_id: 5, name: nil, created_at: Wed, 22 Dec 2021 13:15:53.782148000 UTC +00:00, updated_at: Wed, 22 Dec 2021 13:15:53.782148000 UTC +00:00>
実際の動作
userがitemを持っている状態で build_item メソッドを実行すると、古いレコードが削除される。
irb(main):003:0> user.build_item
  TRANSACTION (0.7ms)  BEGIN
  Item Destroy (1.1ms)  DELETE FROM `items` WHERE `items`.`id` = 12
  TRANSACTION (2.5ms)  COMMIT
=> #<Item:0x00007f857045c6d8 id: nil, user_id: 5, name: nil, created_at: nil, updated_at: nil>