Rails MySQL iLike query

A minha sintaxe está desligada. Quero criar um scope by_name que encontre todos agencies cujo atributo de nome contém o texto passado (sem distinção de maiúsculas).

Eis o que tenho:
class Agency < ActiveRecord::Base
  scope :by_name, ->(agency_name) { where('name ILIKE ?', "%#{agency_name}%") }
end

na consola de Carris eu digito em agencies = Agency.by_name("foo"). Aqui está a consulta gerada:

SELECT `agencies`.* FROM `agencies`  WHERE (name ILIKE '%foo%')

aqui está a mensagem de erro:

Mysql2:: erro: você tem um erro na sua sintaxe SQL; verifique o manual que corresponde à sua versão do servidor MySQL para a direita sintaxe para usar próximo ' ILLIKE '%foo%')

Author: Andrey Deineko, 2015-12-01

2 answers

Acho que deve ser:

 scope :by_name, lambda { |agency_name| 
   where('name LIKE ?', "%#{agency_name}%") # not ILIKE
 }

É no PostgreSQL que a palavra-chave ILIKE pode ser usada em vez de gostar para tornar a correspondência insensível à capitalização, de acordo com a localização activa. Isto não está no padrão SQL, mas é uma extensão PostgreSQL.

Em MySQL você não tem ILIKE. Checkout os docs de MySQL nas funções de comparação de texto .


Bônus - você também pode usar Arel. Dá uma vista de olhos.

scope :by_name, lambda { |agency_name| 
  where(Agency.arel_table[:name].matches("%#{agency_name}%"))
}
 13
Author: Andrey Deineko, 2016-09-09 13:10:26
Sim, porque no MySQL não existe tal coisa. Apenas LIKE. Você pode ter visto ILIKE como uma versão insensível a casos de {[[2]} no PostgreSQL, mas o seu RDBMS atual é diferente.

A tua melhor aposta é usar LOWER em ambos os lados para obter um efeito quase equivalente:

.where('LOWER(name) LIKE LOWER(?)', "%#{agency_name}%")

O crédito a @mu é demasiado curtopara a sua resposta .

 4
Author: D-side, 2017-05-23 11:52:55