2014-01-13 3 views
0

Таблица моих пользователей имеет уникальные индексы в полях электронной почты и имени пользователя. Время от времени ограничение единственности будет нарушено, и будет выбрано исключение ActiveRecord::RecordNotUnique. Это может произойти из-за состояния гонки в проверке уникальности рельсов, когда пользователь дважды отправляет регистрационную форму в быстрой последовательности или когда два пользователя пытаются зарегистрировать одно и то же имя пользователя одновременно.Ручка ActiveRecord :: RecordNotUnique в контроллере регистрации Devise

Когда исключение вызвано двумя последовательными запросами на регистрацию, я хотел бы подписать пользователя. В противном случае, когда ограничение уникальности нарушено редким случаем двух пользователей, регистрирующих одно и то же имя пользователя, я бы хотел отобразить обычная «взятая» ошибка.

Для этого я переопределить действие создания:

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 

Есть ли способ сделать Разрабатывает обрабатывать ActiveRecord::RecordNotUnique исключения и добиться чего-то подобного тому, что я сделал?

+0

Какая версия Devise вы используете? – Ashitaka

ответ

0

У меня была та же проблема.

Исключение выбрано из-за add_index :email, unique => true, добавлено путем разработки модели пользователя (посмотрите в своих миграциях). Это добавляет ограничение уникальности на уровне базы данных, переопределяя валидности frameowrk.

На самом деле я решил отказаться от уникальности индекса электронной почты, так что я могу управлять всем с проверкой рельсов, но на самом деле я не знаю, полностью ли он прав, или если он должен работать таким образом, поскольку это в первый раз я использую разработку с ИППП.

надеюсь, что это поможет.

+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 включен. Или иначе он не будет записывать ошибки из базы данных.

Смежные вопросы