validates_uniqueness_of :name, :case_sensitive => false
załatwia sprawę, ale należy pamiętać, że validates_uniqueness_of
nie nie gwarantują wyjątkowość jeśli masz wiele serwerów / procesów serwera (np uruchomiony phusion passenger wielokrotne kundli, etc) lub serwerze wielowątkowe. To dlatego, że możesz otrzymać taką sekwencję zdarzeń (kolejność jest ważna):
- Proces A otrzymuje żądanie utworzenia nowego użytkownika o nazwie „foo”
- Proces B robi to samo
- Proces A sprawdza unikalność „foo”, pytając DB, czy ta nazwa już istnieje, a DB mówi, że nazwa jeszcze nie istnieje.
- Proces B robi to samo i otrzymuje taką samą odpowiedź
- Proces A przesyła
insert
oświadczenie dla nowego rekordu i kończy się pomyślnie
- Jeśli masz ograniczenie bazy danych wymagające unikalności dla tego pola, proces B prześle
insert
instrukcję dla nowego rekordu i zakończy się niepowodzeniem z brzydkim wyjątkiem serwera, który wraca z adaptera SQL. Jeśli nie masz ograniczenia dotyczącego bazy danych, wstawianie się powiedzie i masz teraz dwa wiersze z „foo” jako nazwą.
Zobacz także „Współbieżność i integralność” w validates_uniqueness_of
dokumentacji Railsów.
Z Ruby on Rails 3rd Edition :
... pomimo swojej nazwy validates_uniqueness_of nie gwarantuje, że wartości kolumn będą unikalne. Wszystko, co może zrobić, to sprawdzić, czy żadna kolumna nie ma takiej samej wartości, jak ta w walidowanym rekordzie w momencie przeprowadzania walidacji. Możliwe jest jednoczesne utworzenie dwóch rekordów, z których każdy ma tę samą wartość dla kolumny, która powinna być unikalna, oraz aby oba rekordy przeszły walidację. Najbardziej niezawodnym sposobem wymuszenia unikalności jest ograniczenie na poziomie bazy danych ”.
Zobacz także doświadczenie tego programisty z validates_uniqueness_of
.
Jednym ze sposobów, w jakie to się często zdarza, są przypadkowe podwójne zgłoszenia ze strony internetowej podczas tworzenia nowego konta. Jest to trudne do rozwiązania, ponieważ użytkownik odzyska drugi (brzydki) błąd i sprawi, że pomyśli, że ich rejestracja się nie powiodła, podczas gdy w rzeczywistości się udało. Najlepszym sposobem, aby temu zapobiec, jest użycie javascript, aby zapobiec podwójnemu przesyłaniu.
W szynach 3 możesz to zrobić w swoim modelu:
validates :name, :uniqueness => true
lub bez wrażliwości na wielkość liter
validates :name, :uniqueness => {:case_sensitive => false}
źródło
Istnieje opcja, w której można określić niewrażliwość na wielkość liter
validates_uniqueness_of :name, :case_sensitive => false
źródło
Jest podobne pytanie, ale odpowiedź jest bardziej interesująca: https://stackoverflow.com/a/6422771
Zasadniczo użycie
:case_sensitive => false
powoduje wykonanie bardzo nieefektywnego zapytania do bazy danych.źródło