在 Devise 注册控制器中处理 ActiveRecord::RecordNotUnique

问题描述 投票:0回答:3

我的用户表在电子邮件和用户名字段上有唯一的索引。有时,唯一性约束会被打破,并且会抛出

ActiveRecord::RecordNotUnique
异常。当用户快速连续两次提交注册表单时,或者当两个用户尝试同时使用相同的用户名注册时,可能会由于 Rails 唯一性验证中的竞争条件而发生这种情况。

当异常是由两个连续的注册请求引起时,我想让用户登录。否则,当两个用户使用同一用户名注册的罕见情况打破唯一性约束时,我想显示通常的“已采取”错误。

为此,我重写了创建操作:

class RegistrationsController < Devise::RegistrationsController
  def create
    begin
      super
    rescue ActiveRecord::RecordNotUnique
      user = User.find_by_email(params[:user][:email])
      if user.present? && user.valid_password?(params[:user][:password])
        # The credentials are valid for the existing user. We can
        # sign them in.
        sign_in(:user, user)
        respond_with user, :location => after_sign_in_path_for(user)
      else
        # The credentials are invalid.
        # This should only happen if multiple users register with the
        # same email at the same time. Now we can simply attempt to
        # register the user again, knowing it will fail, in order to
        # generate the appropriate error messages.
        super
      end
    end        
  end
end

有没有办法让 Devise 处理

ActiveRecord::RecordNotUnique
异常并实现类似于我所做的事情?

ruby-on-rails ruby activerecord devise
3个回答
0
投票

我也有同样的问题。

抛出异常是因为

add_index :email, unique => true
,由设计添加到您的用户模型中(看看您的迁移)。这在数据库级别添加了唯一性约束,覆盖框架验证。

实际上,我决定放弃电子邮件索引的唯一性,以便我可以通过 Rails 验证来管理所有内容,但我实际上不知道它是否完全正确,也不知道它是否应该以这种方式工作,因为这是我第一次正在使用带有 STI 的设备。

希望有帮助。


0
投票

我遇到了类似的问题,可以快速连续多次提交注册表单 - 导致出现所描述的错误。

对我有用的一个简单修复是在提交表单时禁用提交按钮


-1
投票

只需在资源模型中添加

:validatable
即可。最有可能在
user.rb
。它应该看起来像这样:

class User < ActiveRecord::Base
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, 
         :registerable,
         :recoverable,
         :rememberable, 
         :trackable,
         :validatable
end

确保包含

:validatable
。否则它不会捕获数据库中的错误。

© www.soinside.com 2019 - 2024. All rights reserved.