Rails “перевіряє_унікальність_” Чутливість до регістру


95

Ось модель (я використовую SQLLite3):

class School < ActiveRecord::Base

  validates_uniqueness_of :name

end

Наприклад, після додавання "Yale" я не можу додати "Yale", але можу додати "yale". Як я можу зробити регістр перевірки нечутливим?

EDIT: знайшов - перевірка активних записів

Відповіді:


232

validates_uniqueness_of :name, :case_sensitive => falseробить трюк, але слід пам’ятати, що validates_uniqueness_ofце не гарантує унікальності, якщо у вас є кілька серверів / серверних процесів (наприклад, запущений Phusion Passenger, кілька монгрелів тощо) або багатопотоковий сервер. Це тому, що ви можете отримати таку послідовність подій (порядок важливий):

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

Див. Також "Паралельність та цілісність" у validates_uniqueness_ofдокументації Rails.

З Ruby on Rails 3rd Edition :

... незважаючи на свою назву, validates_uniqueness_of насправді не гарантує, що значення стовпців будуть унікальними. Все, що він може зробити, це перевірити, що жоден стовпець не має такого значення, як у записі, який перевіряється на момент перевірки. Можна створити два записи одночасно, кожен з однаковим значенням для стовпця, який повинен бути унікальним, і для обох записів пройти перевірку. Найбільш надійний спосіб забезпечити унікальність - це обмеження на рівні бази даних. "

Дивіться також досвід цього програміста з validates_uniqueness_of.

Одним із способів, як це часто трапляється, є випадкові подвійні подання з веб-сторінки під час створення нового облікового запису. Цю проблему важко вирішити, оскільки те, що користувач отримає назад, є другою (потворною) помилкою, і це змусить їх думати, що їх реєстрація не вдалася, коли насправді це вдалося. Найкращий спосіб, який я знайшов, щоб запобігти цьому, - це просто використовувати javascript, щоб спробувати запобігти подвійному поданню.


4
Як примітка - ось виправлення, яке я надіслав Rails, щоб спробувати вирішити цю проблему, встановивши обмеження рівня db: rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets/…
Jordan Brough

також є проблема багаторічної проблеми "користувач двічі натиснув кнопку подати", але це скоріше виправлення за допомогою: disable_with
Ghoti

78

У рейках 3 ви можете зробити це у своїй моделі:

validates :name, :uniqueness => true

або без чутливості до регістру

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

Це саме те, що я хочу.
Jigar Bhatt

1
Я займаюся Rails більше 10 років. Я не можу повірити, що я просто дізнаюся про цей варіант. У Rails завжди є чомусь новому навчитися ... незалежно від рівня кваліфікації.
danielrice кодує

25

Існує варіант, де можна вказати нечутливість до регістру

  validates_uniqueness_of :name, :case_sensitive => false

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.