Ja, den valideringen skulle göra den typen av sökning och den typen av sökning kommer att göra en tabellskanning.
Du har faktiskt ett par problem här:
- Verifieringen är föremål för tävlingsvillkor eftersom logiken inte finns i databasen där den hör hemma. Databasen bör ansvara för alla dataintegritetsfrågor oavsett Rails-ideologin.
- Din validering utlöser tabellgenomsökningar och ingen gillar tabellgenomsökningar.
Du kan lösa båda dessa problem med ett index. Det första problemet löses genom att använda ett unikt index inuti databasen. Det andra problemet löses genom att indexera resultatet av lower(username)
istället för username
.
AFAIK Rails förstår fortfarande inte index på uttryck så du måste göra två saker:
-
Byt från
schema.rb
tillstructure.sql
för att förhindra att Rails glömmer ditt index. I dinconfig/application.rb
du vill ställa in:config.active_record.schema_format = :sql
Du måste också börja använda
db:structure:*
rake-uppgifter istället fördb:schema:*
uppgifter. När du har bytt tillstructure.sql
, kan du ta bortdb/schema.rb
eftersom det inte kommer att uppdateras eller användas längre; du vill också börja spåradb/structure.sql
i revisionskontroll. -
Skapa indexet för hand genom att skriva lite SQL i en migrering. Det här är enkelt:
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
Naturligtvis kommer detta att lämna dig med PostgreSQL-specifika saker men det är inget att oroa sig för eftersom ActiveRecord inte ger dig någon användbar portabilitet ändå.