クイズ:なぜバリデーションエラーになるでしょう
要約
- railsのcallbackで中間テーブルを生成する方法をミスるとvalidationエラーになるアンチパターン
詳細
- モデル構成
class User < ApplicationRecord
has_many :notification_settings, dependent: :destroy
has_many :notifications, through: :notification_settings, dependent: :destroy
after_create :create_default_notifications
end
class NotificationSetting < ApplicationRecord
belongs_to :user
belongs_to :notification
validates :user_id, uniqueness: { scope: [:notification_id] }
end
class Notification < ApplicationRecord
has_many :notification_settings, dependent: :destroy
has_many :users, through: :notification_settings, dependent: :destroy
end
とかで、ユーザに通知設定が複数ひもづいている状態で、ユーザが作成されたタイミングでデフォルトの通知設定を作りたくてcreate_default_notifications
の中で
def create_default_notifications
self.notifications = Notification.all
end
てやっていると一見OKっぽいんだけど、validates :user_id, uniqueness: { scope: [:notification_id] }
で引っかかってvalildationエラーになる。
理由
self.notifications = Notification.all
が評価されたタイミングでNotificationSettingにinsertが発行されてしまって、
その後autosaveも動くので、結果2回createされてしまってuniqueじゃなくなってエラーになる。
has_manyにassignすると即insertされるというのがわかりにくかったという問題。
=はsaveされないという思い込みでした。
修正
丁寧に1件1件buildする
Notification.all.each do |notification|
self.notification_settings.build(notification: notification)
end
Author And Source
この問題について(クイズ:なぜバリデーションエラーになるでしょう), 我々は、より多くの情報をここで見つけました https://qiita.com/yuma_nishizaki/items/ae915965e02853cf803a著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .