Ja, diese Validierung würde diese Art von Abfrage durchführen, und diese Art von Abfrage wird einen Tabellenscan durchführen.
Sie haben hier tatsächlich ein paar Probleme:
- Die Validierung unterliegt Race Conditions, da die Logik nicht in der Datenbank ist, wo sie hingehört. Die Datenbank sollte unabhängig von der üblichen Rails-Ideologie für alle Fragen der Datenintegrität verantwortlich sein.
- Ihre Validierung löst Tabellenscans aus und niemand mag Tabellenscans.
Sie können diese beiden Probleme mit einem Index lösen. Das erste Problem wird gelöst, indem ein eindeutiger Index innerhalb der Datenbank verwendet wird. Das zweite Problem wird gelöst, indem das Ergebnis von lower(username)
indiziert wird statt username
.
AFAIK Rails versteht immer noch keine Indizes für Ausdrücke, also müssen Sie zwei Dinge tun:
-
Wechseln Sie von
schema.rb
zustructure.sql
damit Rails Ihren Index nicht vergisst. In Ihrerconfig/application.rb
Sie möchten Folgendes festlegen:config.active_record.schema_format = :sql
Sie müssen auch damit beginnen,
db:structure:*
zu verwenden Rechenaufgaben anstelle vondb:schema:*
Aufgaben. Sobald Sie zustructure.sql
gewechselt sind , können Siedb/schema.rb
löschen da es nicht mehr aktualisiert oder verwendet wird; Sie sollten auch mit dem Tracking vondb/structure.sql
beginnen in der Revisionskontrolle. -
Erstellen Sie den Index von Hand, indem Sie in einer Migration ein wenig SQL schreiben. Das ist ganz einfach:
def up connection.execute(%q{ create index idx_users_lower_username on users(lower(username)) }) end def down connection.execute(%q{ drop index idx_users_lower_username }) end
Natürlich werden Sie dadurch mit PostgreSQL-spezifischen Dingen zurückbleiben, aber das ist kein Grund zur Sorge, da ActiveRecord Ihnen sowieso keine nützliche Portabilität bietet.