加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

ruby-on-rails – 未获救的ActiveRecord异常

发布时间:2020-12-17 02:59:31 所属栏目:百科 来源:网络整理
导读:我有以下代码块: unless User.exist?(...) begin user = User.new(...) # Set more attributes of user user.save! rescue ActiveRecord::RecordInvalid,ActiveRecord::RecordNotUnique = e # Check if that user was created in the meantime user = User.
我有以下代码块:

unless User.exist?(...)
  begin
    user = User.new(...)
    # Set more attributes of user
    user.save!
  rescue ActiveRecord::RecordInvalid,ActiveRecord::RecordNotUnique => e
    # Check if that user was created in the meantime
    user = User.exists?(...)
    raise e if user.nil?
  end
end

原因是,正如您可能猜到的那样,多个进程可能同时调用此方法来创建用户(如果它尚不存在),因此当第一个进入块并开始初始化新用户时,设置属性并最终调用save!,可能已经创建了用户.
在这种情况下,我想再次检查用户是否存在,如果它仍然没有,则只引发异常(=如果在此期间没有其他进程创建它).

问题是,定期从保存中引发ActiveRecord :: RecordInvalid异常!并没有从救援区获救.
有任何想法吗?

编辑:

好吧,这很奇怪.我肯定错过了什么.我根据Simone的提示重构了代码,看起来像这样:

unless User.find_by_email(...).present?
  # Here we know the user does not exist yet
  user = User.new(...)
  # Set more attributes of user
  unless user.save
    # User could not be saved for some reason,maybe created by another request?
    raise StandardError,"Could not create user for order #{self.id}." unless User.exists?(:email => ...)
  end
end

现在我得到以下异常:

ActiveRecord::RecordNotUnique: Mysql::DupEntry: Duplicate entry 'foo@bar.com' for key 'index_users_on_email': INSERT INTO `users` ...

抛出“除非user.save”的行.
怎么可能? Rails认为可以创建用户,因为电子邮件是唯一的,但是Mysql唯一索引会阻止插入?这有多大可能?怎么可以避免呢?

解决方法

在这种情况下,您可能希望使用迁移在用户表键上创建唯一索引,以便数据库引发错误.

另外,不要忘记在用户模型中添加validates_uniqueness_of验证.

验证并不总能防止重复数据(两个并发请求以相同的毫秒写入的可能性极小).
如果将validates_uniqueness_of与索引结合使用,则不需要所有代码.

unless User.exist?(...)
  begin
    user = User.new(...)
    # Set more attributes of user
    user.save!
  rescue ActiveRecord::RecordInvalid,ActiveRecord::RecordNotUnique => e
    # Check if that user was created in the meantime
    user = User.exists?(...)
    raise e if user.nil?
  end
end

user = User.new(...)
# Set more attributes of user
if user.save
  # saved
else
  # user.errors will return
  # the list of errors
end

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读