Ja, die validatie zou dat soort zoekopdrachten doen en dat soort zoekopdrachten gaan een tabelscan uitvoeren.
Je hebt hier eigenlijk een paar problemen:
- De validatie is onderhevig aan race-voorwaarden omdat de logica niet in de database staat waar deze thuishoort. De database zou verantwoordelijk moeten zijn voor alle problemen met gegevensintegriteit, ongeacht de gebruikelijke Rails-ideologie.
- Uw validatie activeert tabelscans en niemand houdt van tabelscans.
U kunt beide problemen met één index oplossen. Het eerste probleem wordt opgelost door een unieke index in de database te gebruiken. Het tweede probleem wordt opgelost door het resultaat van lower(username)
. te indexeren in plaats van username
.
AFAIK Rails begrijpt nog steeds geen indexen op uitdrukkingen, dus je zult twee dingen moeten doen:
-
Overschakelen van
schema.rb
naarstructure.sql
om te voorkomen dat Rails uw index vergeet. In uwconfig/application.rb
u wilt instellen:config.active_record.schema_format = :sql
U moet ook de
db:structure:*
. gaan gebruiken rake taken in plaats van dedb:schema:*
taken. Zodra u bent overgeschakeld naarstructure.sql
, kunt udb/schema.rb
. verwijderen omdat het niet meer zal worden bijgewerkt of gebruikt; u wilt ook beginnen met het bijhouden vandb/structure.sql
in revisiebeheer. -
Maak de index met de hand door een stukje SQL te schrijven in een migratie. Dit is eenvoudig:
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
Dit laat je natuurlijk achter met PostgreSQL-specifieke dingen, maar dat is niets om je zorgen over te maken, aangezien ActiveRecord je sowieso geen bruikbare portabiliteit geeft.