has_oneにするとちゃんと維持しようとするんだと関心したのでメモ
環境
rails (5.1.6)
例
以下のようなモデルがあるとする
class User < ApplicationRecord
has_one :profile
end
class Profile < ApplicationRecord
belongs_to :user , optional: true
end
こんな感じで変数としてcreateして
user = User.create(name:"test1")
(0.4ms) SET NAMES utf8mb4, @@SESSION.sql_mode = CONCAT(CONCAT(@@sql_mode, ',STRICT_ALL_TABLES'), ',NO_AUTO_VALUE_ON_ZERO'), @@SESSION.sql_auto_is_null = 0, @@SESSION.wait_timeout = 2147483
(0.2ms) BEGIN
SQL (0.3ms) INSERT INTO `users` (`name`, `created_at`, `updated_at`) VALUES ('test1', '2018-07-06 13:26:56', '2018-07-06 13:26:56')
(0.7ms) COMMIT
=>
profile1 = Profile.create(birthday:Time.new(1990,1,10))
(0.2ms) BEGIN
SQL (0.3ms) INSERT INTO `profiles` (`birthday`, `created_at`, `updated_at`) VALUES ('1990-01-09 15:00:00', '2018-07-06 13:27:01', '2018-07-06 13:27:01')
(1.2ms) COMMIT
=>
代入すると入る
user.profile = profile1
Profile Load (1.1ms) SELECT `profiles`.* FROM `profiles` WHERE `profiles`.`user_id` = 1 LIMIT 1
(0.2ms) BEGIN
SQL (2.0ms) UPDATE `profiles` SET `user_id` = 1, `updated_at` = '2018-07-06 13:27:07' WHERE `profiles`.`id` = 1
(0.3ms) COMMIT
=>
ここまでは普通の話なんですが
他の値を代入すると、ちゃんとIDのかき消し処理をする
profile2 = Profile.create(birthday:Time.new(1989,1,10))
(0.2ms) BEGIN
SQL (2.0ms) INSERT INTO `profiles` (`birthday`, `created_at`, `updated_at`) VALUES ('1989-01-09 15:00:00', '2018-07-06 13:28:36', '2018-07-06 13:28:36')
(1.9ms) COMMIT
=>
user.profile = profile2
(0.3ms) BEGIN
SQL (0.6ms) UPDATE `profiles` SET `user_id` = NULL, `updated_at` = '2018-07-06 13:28:46' WHERE `profiles`.`id` = 1
SQL (0.4ms) UPDATE `profiles` SET `user_id` = 1, `updated_at` = '2018-07-06 13:28:46' WHERE `profiles`.`id` = 2
(0.4ms) COMMIT
=>
ただし手動で入れるとそうはならないので注意
profile3 = Profile.create(user_id:user.id,birthday:Time.new(1989,1,10))
(0.3ms) BEGIN
SQL (0.5ms) INSERT INTO `profiles` (`user_id`, `birthday`, `created_at`, `updated_at`) VALUES (1, '1989-01-09 15:00:00', '2018-07-06 13:29:39', '2018-07-06 13:29:39')
(1.0ms) COMMIT
=>
Profile.where(user_id:user.id).size
(0.6ms) SELECT COUNT(*) FROM `profiles` WHERE `profiles`.`user_id` = 1
=> 2