我的用户表在电子邮件和用户名字段上有唯一的索引。有时,唯一性约束会被打破,并且会抛出
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
异常并实现类似于我所做的事情?
我也有同样的问题。
抛出异常是因为
add_index :email, unique => true
,由设计添加到您的用户模型中(看看您的迁移)。这在数据库级别添加了唯一性约束,覆盖框架验证。
实际上,我决定放弃电子邮件索引的唯一性,以便我可以通过 Rails 验证来管理所有内容,但我实际上不知道它是否完全正确,也不知道它是否应该以这种方式工作,因为这是我第一次正在使用带有 STI 的设备。
希望有帮助。
我遇到了类似的问题,可以快速连续多次提交注册表单 - 导致出现所描述的错误。
对我有用的一个简单修复是在提交表单时禁用提交按钮
只需在资源模型中添加
: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