Solução do pobre homem
Se você é capaz de criar uma função, você pode usar esta. Eu compilei a lista começando aqui e adicionado a ele ao longo do tempo. É bem completo. Você pode até querer remover alguns caracteres:
CREATE OR REPLACE FUNCTION lower_unaccent(text)
RETURNS text AS
$func$
SELECT lower(translate($1
, '¹²³áàâãäåāăąÀÁÂÃÄÅĀĂĄÆćčç©ĆČÇĐÐèéêёëēĕėęěÈÊËЁĒĔĖĘĚ€ğĞıìíîïìĩīĭÌÍÎÏЇÌĨĪĬłŁńňñŃŇÑòóôõöōŏőøÒÓÔÕÖŌŎŐØŒř®ŘšşșߊŞȘùúûüũūŭůÙÚÛÜŨŪŬŮýÿÝŸžżźŽŻŹ'
, '123aaaaaaaaaaaaaaaaaaacccccccddeeeeeeeeeeeeeeeeeeeeggiiiiiiiiiiiiiiiiiillnnnnnnooooooooooooooooooorrrsssssssuuuuuuuuuuuuuuuuyyyyzzzzzz'
));
$func$ LANGUAGE sql IMMUTABLE;
Sua consulta deve funcionar assim:
find(:all, :conditions => ["lower_unaccent(name) LIKE ?", "%#{search.downcase}%"])
Para pesquisas ancoradas à esquerda, você pode utilizar um índice na função para muito resultados rápidos:
CREATE INDEX tbl_name_lower_unaccent_idx
ON fest (lower_unaccent(name) text_pattern_ops);
Para consultas como:
SELECT * FROM tbl WHERE (lower_unaccent(name)) ~~ 'bob%'
Solução adequada
No PostgreSQL 9.1+ , com os privilégios necessários, você pode apenas:
CREATE EXTENSION unaccent;
que fornece uma função
unaccent()
, fazendo o que você precisa (exceto para lower()
, apenas use isso adicionalmente, se necessário). Leia o manual sobre esta extensão
.Também disponível para PostgreSQL 9.0 mas
CREATE EXTENSION
sintaxe é nova em 9.1. Mais sobre unaccent e índices: