Techioz Blog

Rails: 更新時に「すでに取得されています」エラーが発生する

概要

アプリは属性を検索または初期化します。

booking = Booking.where(deal_id: params["id"]).first_or_initialize

次に、いくつかの追加の属性を更新します

    if booking.update!(
        guests: guests,
        names: names,
        time: time)

このコードではエラーが発生します

Validation failed: Deal has already been taken

検証コードは

  validates_uniqueness_of :deal_id, allow_blank: true, scope: [:experience_id, :time], unless: -> {deal_id.zero? }

最初に first_or_initialize を実行すると、「すでに取得されています」というエラーが発生するのはなぜですか?

ありがとう

解決策

これは、experience_id、time の範囲内に同じ deal_id で予約がすでにあることを意味します

これは、この一意性検証をモデルに追加したときにデータベースにすでにレコードがあった場合に発生する可能性があります。

しかし、これはまったく必要ありません。 deal_id だけを使用した first_or_initialize では、deal_id、experience_id、time の組み合わせは妨げられません

さらに、競合状態から保護することはできません

更新する前に、デバッグでそのようなレコード数を確認できます。

Booking.where(
  deal_id: booking.deal_id,
  experience_id: booking.experience_id,
  time: time,
).count