Рельсы 3. Проверка уникальности электронной почты и чувствительности к регистру

Я разрабатываю приложение в Rails 3 и при регистрации мне нужно, чтобы пользователь вводил свой адрес электронной почты, и мне нужно, чтобы он был уникальным и чувствительным к регистру. То есть никто не должен регистрироваться с [email protected], когда [email protected] уже существует в базе данных.

Это мой код, и он отключает приложение:

validates :email, :presence => true, :uniqueness => true, :case_sensitive => true,
                      :format => {:with => /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i}

Что с ним не так?

Ответ 1

Пожалуйста, не используйте там чувствительный к регистру случай!!! Он будет загружать всех пользователей! Так что если у вас 100 000 пользователей. сначала он будет брать их всех с LOWER (электронная почта). Это может быть ОЧЕНЬ медленно, и он не будет использовать ваш индекс по электронной почте.

Вот статья, которую я нашел сейчас только по этой теме: http://techblog.floorplanner.com/post/20528527222/case-insensitive-validates-uniqueness-of-slowness

Я предлагаю: Запустить запрос, чтобы все электронные письма были удалены и сделать фильтр до проверки, чтобы изменить атрибут электронной почты, чтобы у вас не было символов с верхним регистром в этом столбце.

User.update_all('email = LOWER(email)')

перед фильтром:

before_validation :downcase_email

private

def downcase_email
  self.email = email.downcase if email.present?
end

Ответ 2

Для проверки валидации Rails 3 вам нужно вставить блокировку, нечувствительную к кассе, таким образом

validates :email, :uniqueness => { :case_sensitive => false }

Ответ 3

У меня нет репутации, чтобы прокомментировать принятый ответ, но @medBo спросил, как это ведет себя в Rails 4. Для справки при использовании Rails 4.2 + MySQL, если я укажу

validates :username, uniqueness: { case_sensitive: false }

ActiveRecord выполняет этот запрос:

SELECT  1 AS one FROM `users` WHERE `users`.`username` = 'TEST_USER' LIMIT 1

В этом случае поиск не чувствителен к регистру. Но когда я установил:

validates :username, uniqueness: { case_sensitive: false }

он выполняет:

SELECT  1 AS one FROM `users` WHERE `users`.`username` = BINARY 'TEST_USER'

Оператор BINARY гарантирует, что поиск чувствителен к регистру, не выбирая всех пользователей, что означает для моей установки, по крайней мере, флаг case_sensitive doesn ' t страдают от проблемы производительности, которую @Michael Koper отмечает для более ранних версий Rails. Я не могу прокомментировать, как работает ActiveRecord для других настроек базы данных.

Ответ 4

Я не уверен, что с помощью этого синтаксиса можно сделать проверку нечувствительности к регистру (по крайней мере, я не нашел для нее никакой документации).

Вы должны иметь возможность проверить нечувствительность к регистру, как это, хотя:

validates_uniqueness_of :email, :case_sensitive => false

Без дополнительной информации о сбое, который вы получаете, я не могу больше помочь.