我的用户表在电子邮件和用户名字段中有唯一索引。偶尔会出现唯一性约束,并抛出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
例外并实现类似于我所做的事情?
答案 0 :(得分:0)
由于add_index :email, unique => true
引发了异常,通过设计添加到您的用户模型(查看迁移)。这会在数据库级别添加唯一性约束,从而覆盖frameowrk验证。
实际上我决定放弃电子邮件索引的唯一性,以便我可以使用rails验证来管理所有内容,但实际上我不知道它是否完全正确,也不知道它是否应该以这种方式工作,因为它是第一个我正在使用STI的设计。
希望它有所帮助。答案 1 :(得分:-2)
只需在资源模型中添加: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
。否则它不会从数据库中捕获错误。