Search code examples
ruby-on-railsrubyvalidationrails-activerecord

Rails: "has already been taken" error on update


The app finds or initializes by an attribute:

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

Then updates some additional attributes

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

This code gives me the error

Validation failed: Deal has already been taken

The validation code is

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

Why is it giving a "has already been taken" error when first it does first_or_initialize?

Thanks


Solution

  • It means you already have Booking with same deal_id in scope of experience_id, time

    This could happen if you already had records in the database at the time when you added this uniqueness validation to model

    But this is not necessary at all. Your first_or_initialize with just deal_id doesn't prevent of combination deal_id, experience_id and time

    Besides, it doesn't protect you from race condition

    You can check such records count with debug before updating:

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