Sí, esa validación haría ese tipo de consulta y ese tipo de consulta hará un escaneo de tabla.
De hecho, tienes un par de problemas aquí:
- La validación está sujeta a condiciones de carrera porque la lógica no está en la base de datos a la que pertenece. La base de datos debe ser responsable de todos los problemas de integridad de datos, independientemente de la ideología habitual de Rails.
- Su validación desencadena escaneos de tablas y a nadie le gustan los escaneos de tablas.
Puede resolver ambos problemas con un índice. El primer problema se resuelve utilizando un índice único dentro de la base de datos. El segundo problema se resuelve indexando el resultado de lower(username)
en lugar de username
.
AFAIK Rails todavía no entiende los índices de las expresiones, por lo que tendrá que hacer dos cosas:
-
Cambiar de
schema.rb
astructure.sql
para evitar que Rails se olvide de su índice. En tuconfig/application.rb
querrás configurar:config.active_record.schema_format = :sql
También tendrás que empezar a usar
db:structure:*
rake tareas en lugar dedb:schema:*
Tareas. Una vez que haya cambiado astructure.sql
, puede eliminardb/schema.rb
ya que no se actualizará ni usará más; también querrá comenzar a rastreardb/structure.sql
en el control de revisión. -
Cree el índice a mano escribiendo un poco de SQL en una migración. Esto es fácil:
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
Por supuesto, esto lo dejará con cosas específicas de PostgreSQL, pero eso no es motivo de preocupación, ya que ActiveRecord no le brinda ninguna portabilidad útil de todos modos.