Rails "validates_uniqueness_of" чувствительность к регистру - PullRequest
84 голосов
/ 27 марта 2009

Вот модель (я использую SQLLite3):

class School < ActiveRecord::Base

  validates_uniqueness_of :name

end

Например, после добавления «Йель» я не могу добавить «Йель», но может добавить «Йель». Как я могу сделать валидацию без учета регистра?

РЕДАКТИРОВАТЬ: Найдено - Активные проверки записей

Ответы [ 4 ]

221 голосов
/ 27 марта 2009

validates_uniqueness_of :name, :case_sensitive => false делает свое дело, но вы должны иметь в виду, что validates_uniqueness_of делает не гарантируют уникальность, если у вас есть несколько серверов / серверных процессов (например, запуск Phusion Passenger, несколько Mongrels и т. Д.) Или многопоточный сервер. Это потому, что вы можете получить эту последовательность событий (порядок важен):

  1. Процесс A получает запрос на создание нового пользователя с именем 'foo'
  2. Процесс B делает то же самое
  3. Процесс A проверяет уникальность 'foo', спрашивая БД, существует ли это имя, и БД говорит, что имя еще не существует.
  4. Процесс B делает то же самое и получает тот же ответ
  5. Процесс A отправляет оператор insert для новой записи и успешно
  6. Если у вас есть ограничение базы данных, требующее уникальности для этого поля, Процесс B отправит оператор insert для новой записи и fail с уродливым серверным исключением, которое возвращается из адаптера SQL. Если у вас нет ограничения базы данных, вставка будет выполнена успешно, и теперь у вас есть две строки с именем 'foo'.

См. Также «Параллельность и целостность» в документации validates_uniqueness_of Rails.

С Ruby on Rails 3-е издание :

... несмотря на название, validates_uniqueness_of действительно не гарантирует, что значения столбцов будут уникальными. Все, что он может сделать, это убедиться, что ни один столбец не имеет того же значения, что и в проверяемой записи во время проверки. Возможно одновременное создание двух записей, каждая из которых имеет одинаковое значение для столбца, который должен быть уникальным, и чтобы обе записи прошли проверку. Самый надежный способ обеспечить уникальность - это ограничение на уровне базы данных. "

См. Также опыт этого программиста с validates_uniqueness_of.

Одним из способов, которым это обычно происходит, является случайное двойное представление с веб-страницы при создании новой учетной записи. Это трудно решить, потому что пользователь получит вторую (некрасивую) ошибку, и это заставит их думать, что их регистрация не удалась, хотя в действительности это удалось. Лучший способ предотвратить это - использовать javascript, чтобы предотвратить двойное представление.

70 голосов
/ 27 июля 2011

В рельсах 3 вы можете сделать это в вашей модели:

validates :name, :uniqueness => true

или без учета регистра

validates :name, :uniqueness => {:case_sensitive => false}
21 голосов
/ 27 марта 2009

Существует опция, в которой вы можете указать регистр нечувствительности

  validates_uniqueness_of :name, :case_sensitive => false
1 голос
/ 22 июня 2013

Есть похожий вопрос, но ответ более интересен: https://stackoverflow.com/a/6422771

По сути, использование :case_sensitive => false выполняет очень неэффективный запрос к базе данных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...