当たり前といえば当たり前なんだけど、冪等性保つ動きを期待しちゃう側面もあるのでメモ
環境
$ bin/rails -v Rails 5.2.2
概要
relationを行っているモデルに対して create_{{モデル名}}
というメソッドを実行すると連動したレコードが作れるが実行するたびに作られてしまうので注意
例
今回使うモデル
# == Schema Information # # Table name: users # # id :bigint(8) not null, primary key # name :string(255) # created_at :datetime not null # updated_at :datetime not null # class User < ApplicationRecord has_many :message end
# == Schema Information # # Table name: messages # # id :bigint(8) not null, primary key # name :string(255) # user_id :integer # created_at :datetime not null # updated_at :datetime not null # class Message < ApplicationRecord belongs_to :user end
実際のコード
Message
と一緒に User
を作りたい場合にbuild_xxxを使うと以下のように作ることができる
message = Message.new #=> #<Message id: nil, name: nil, user_id: nil, created_at: nil, updated_at: nil> message.build_user #=> #<User id: nil, name: nil, created_at: nil, updated_at: nil> message.save! # (0.2ms) BEGIN # User Create (0.3ms) INSERT INTO `users` (`created_at`, `updated_at`) VALUES ('2018-12-23 16:58:57', '2018-12-23 16:58:57') # Message Create (0.2ms) INSERT INTO `messages` (`user_id`, `created_at`, `updated_at`) VALUES (3, '2018-12-23 16:58:57', '2018-12-23 16:58:57') # (1.9ms) COMMIT # => true
create_xxxも使うと同様に作ることができるが、冪等性があるわけではないので呼ぶたびに新しくレコードがつくられてしまう。
message.create_user # (0.1ms) BEGIN # User Create (0.9ms) INSERT INTO `users` (`created_at`, `updated_at`) VALUES ('2018-12-23 17:02:05', '2018-12-23 17:02:05') # (0.5ms) COMMIT #=> #<User id: 4, name: nil, created_at: "2018-12-23 17:02:05", updated_at: "2018-12-23 17:02:05"> message.create_user # (0.1ms) BEGIN # User Create (2.0ms) INSERT INTO `users` (`created_at`, `updated_at`) VALUES ('2018-12-23 17:02:06', '2018-12-23 17:02:06') # (0.4ms) COMMIT #=> #<User id: 5, name: nil, created_at: "2018-12-23 17:02:06", updated_at: "2018-12-23 17:02:06"> message.create_user # (0.1ms) BEGIN # User Create (0.2ms) INSERT INTO `users` (`created_at`, `updated_at`) VALUES ('2018-12-23 17:02:11', '2018-12-23 17:02:11') # (1.5ms) COMMIT #=> #<User id: 6, name: nil, created_at: "2018-12-23 17:02:11", updated_at: "2018-12-23 17:02:11">
既にある場合には作られたくない、などをするときは
message.create_user if message.user.nil?
のようにしてあげないといけないので注意。