Schienen "validates_uniqueness_of" Groß- / Kleinschreibung beachten

93

Hier ist das Modell (ich verwende SQLLite3):

class School < ActiveRecord::Base

  validates_uniqueness_of :name

end

Zum Beispiel, nachdem ich hinzufügen „Yale“, kann ich nicht „Yale“ hinzufügen , aber kann hinzufügen „yale.“ Wie kann ich den Validierungsfall unempfindlich machen?

BEARBEITEN: Gefunden - Aktive Datensatzvalidierungen

GeekJock
quelle

Antworten:

232

validates_uniqueness_of :name, :case_sensitive => falsemacht den Trick, aber Sie sollten bedenken, dass validates_uniqueness_ofdies keine Eindeutigkeit garantiert, wenn Sie mehrere Server / Serverprozesse (z. B. Phusion Passenger, mehrere Mongrels usw.) oder einen Multithread-Server haben. Das liegt daran, dass Sie möglicherweise diese Abfolge von Ereignissen erhalten (die Reihenfolge ist wichtig):

  1. Prozess A erhält die Anforderung, einen neuen Benutzer mit dem Namen 'foo' zu erstellen.
  2. Prozess B macht dasselbe
  3. Prozess A überprüft die Eindeutigkeit von 'foo', indem er die Datenbank fragt, ob dieser Name noch vorhanden ist, und die Datenbank sagt, dass der Name noch nicht vorhanden ist.
  4. Prozess B macht das Gleiche und erhält die gleiche Antwort
  5. Prozess A sendet die insertAnweisung für den neuen Datensatz und ist erfolgreich
  6. Wenn Sie eine Datenbankeinschränkung haben, die eine Eindeutigkeit für dieses Feld erfordert, sendet Prozess B die insertAnweisung für den neuen Datensatz und schlägt mit einer hässlichen Serverausnahme fehl , die vom SQL-Adapter zurückkommt. Wenn Sie keine Datenbankeinschränkung haben, ist die Einfügung erfolgreich und Sie haben jetzt zwei Zeilen mit dem Namen 'foo'.

Siehe auch "Parallelität und Integrität" in der validates_uniqueness_ofRails-Dokumentation.

Von Ruby on Rails 3. Auflage :

... trotz seines Namens garantiert validates_uniqueness_of nicht wirklich, dass Spaltenwerte eindeutig sind. Sie können lediglich überprüfen, ob keine Spalte den gleichen Wert hat wie der Datensatz, der zum Zeitpunkt der Validierung validiert wird. Es ist möglich, dass zwei Datensätze gleichzeitig erstellt werden, jeder mit demselben Wert für eine Spalte, die eindeutig sein soll, und dass beide Datensätze die Validierung bestehen. Der zuverlässigste Weg, um die Eindeutigkeit durchzusetzen, ist eine Einschränkung auf Datenbankebene. "

Siehe auch die Erfahrung dieses Programmierers mit validates_uniqueness_of.

Eine Möglichkeit, wie dies häufig vorkommt, sind versehentliche doppelte Übermittlungen von einer Webseite beim Erstellen eines neuen Kontos. Dies ist schwer zu lösen, da der Benutzer den zweiten (hässlichen) Fehler zurückerhält und denkt, dass die Registrierung fehlgeschlagen ist, obwohl dies in Wirklichkeit erfolgreich war. Der beste Weg, dies zu verhindern, besteht darin, Javascript zu verwenden, um eine doppelte Übermittlung zu verhindern.

Jordan Brough
quelle
4
Als Hinweis: Hier ist ein Patch, den ich bei Rails eingereicht habe, um zu versuchen, dieses Problem durch Verwendung von Einschränkungen auf DB-Ebene zu beheben: rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets/…
Jordan Brough
Es gibt auch das mehrjährige Problem "Benutzer hat auf die Schaltfläche" Senden "doppelt geklickt", aber das ist eher eine Lösung mit: disable_with
Ghoti
76

In Schienen 3 können Sie dies in Ihrem Modell tun:

validates :name, :uniqueness => true

oder ohne case_sensitivity

validates :name, :uniqueness => {:case_sensitive => false}
MaximusDominus
quelle
Genau das will ich.
Jigar Bhatt
1
Ich mache Rails seit über 10 Jahren. Ich kann nicht glauben, dass ich gerade etwas über diese Option lerne. In Rails gibt es immer etwas Neues zu lernen ... unabhängig von der Fähigkeitsstufe.
Danielricecodes
24

Es gibt eine Option, bei der Sie die Groß- und Kleinschreibung nicht angeben können

  validates_uniqueness_of :name, :case_sensitive => false
vrish88
quelle
1

Es gibt eine ähnliche Frage, aber die Antwort ist interessanter: https://stackoverflow.com/a/6422771

Grundsätzlich führt using :case_sensitive => falseeine sehr ineffiziente Datenbankabfrage durch.

Victor S.
quelle