Рельсы 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
Без дополнительной информации о сбое, который вы получаете, я не могу больше помочь.