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
CodePudding user response:
try to run without update
method without !
to see where validation has failed
result = booking.update(
guests: guests,
names: names,
time: time)
result.errors # <= see related errors here
CodePudding user response:
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