简体   繁体   English

Rails:更新时出现“已采取”错误

[英]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?为什么它在第一次执行 first_or_initialize 时会给出“已被占用”错误?

Thanks谢谢

try to run without update method without !尝试在没有update方法的情况下运行! to see where validation has failed查看验证失败的地方

result = booking.update(
        guests: guests,
        names: names,
        time: time)
result.errors # <= see related errors here

It means you already have Booking with same deal_id in scope of experience_id , time这意味着您已经在experience_id的 scope 中拥有相同deal_idBookingtime

This could happen if you already had records in the database at the time when you added this uniqueness validation to model如果在向 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您的first_or_initialize仅使用deal_id不会阻止组合deal_idexperience_id和 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
# This implies the first record

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

# Update the attributes you want

# This will update the record in the database

booking.save!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM