has_oneにするとちゃんと維持しようとするんだと関心したのでメモ
環境
rails (5.1.6)
例
以下のようなモデルがあるとする
# == Schema Information # # Table name: users # # id :bigint(8) not null, primary key # name :string(255) default(""), not null # created_at :datetime not null # updated_at :datetime not null # class User < ApplicationRecord has_one :profile end
# == Schema Information # # Table name: profiles # # id :bigint(8) not null, primary key # user_id :bigint(8) # birthday :datetime not null # created_at :datetime not null # updated_at :datetime not null # 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 => #<User id: 1, name: "test1", created_at: "2018-07-06 13:26:56", updated_at: "2018-07-06 13:26:56"> 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 => #<Profile id: 1, user_id: nil, birthday: "1990-01-09 15:00:00", created_at: "2018-07-06 13:27:01", updated_at: "2018-07-06 13:27:01">
代入すると入る
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 => #<Profile id: 1, user_id: 1, birthday: "1990-01-09 15:00:00", created_at: "2018-07-06 13:27:01", updated_at: "2018-07-06 13:27:07">
ここまでは普通の話なんですが 他の値を代入すると、ちゃんと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 => #<Profile id: 2, user_id: nil, birthday: "1989-01-09 15:00:00", created_at: "2018-07-06 13:28:36", updated_at: "2018-07-06 13:28:36"> 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 => #<Profile id: 2, user_id: 1, birthday: "1989-01-09 15:00:00", created_at: "2018-07-06 13:28:36", updated_at: "2018-07-06 13:28:46">
ただし手動で入れるとそうはならないので注意
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 id: 3, user_id: 1, birthday: "1989-01-09 15:00:00", created_at: "2018-07-06 13:29:39", updated_at: "2018-07-06 13:29:39"> Profile.where(user_id:user.id).size (0.6ms) SELECT COUNT(*) FROM `profiles` WHERE `profiles`.`user_id` = 1 => 2