Sim, essa validação faria esse tipo de consulta e esse tipo de consulta fará uma verificação de tabela.
Você realmente tem alguns problemas aqui:
- A validação está sujeita a condições de corrida porque a lógica não está no banco de dados ao qual pertence. O banco de dados deve ser responsável por todos os problemas de integridade de dados, independentemente da ideologia usual do Rails.
- Sua validação aciona verificações de tabela e ninguém gosta de verificações de tabela.
Você pode resolver esses dois problemas com um índice. O primeiro problema é resolvido usando um índice exclusivo dentro do banco de dados. O segundo problema é resolvido indexando o resultado de
lower(username)
em vez de username
. O AFAIK Rails ainda não entende índices em expressões, então você terá que fazer duas coisas:
-
Mudar deschema.rb
parastructure.sql
para evitar que o Rails esqueça seu índice. Em seuconfig/application.rb
você vai querer definir:
config.active_record.schema_format = :sql
Você também terá que começar a usar odb:structure:*
tarefas de rake em vez dodb:schema:*
tarefas. Depois de mudar parastructure.sql
, você pode excluirdb/schema.rb
já que não será mais atualizado ou usado; você também vai querer começar a rastreardb/structure.sql
no controle de revisão.
-
Crie o índice manualmente escrevendo um pouco de SQL em uma migração. Isso é facil:
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
É claro que isso deixará você com coisas específicas do PostgreSQL, mas isso não é nada para se preocupar, já que o ActiveRecord não oferece nenhuma portabilidade útil de qualquer maneira.