Buscador "Generico" para un solo modelo del dominio - Rails

11 views
Skip to first unread message

Nicolas Zuasti

unread,
Jul 24, 2012, 1:10:50 PM7/24/12
to p-s-f
Gente me encontre en la necesidad de "imitar" una busqueda de texto completa (full text search) y bien a la urugaya no queria complicarme instalando un software de terceros que me hiciera de servidor de dicho servicio.

Por este motivo, y porque estoy usando un sistema que NO tiene muchos miles de millones de lineas, programe un metodo pseudo-generico que ejecuta una busqueda por cada atributo de tipo string de la clase del dominio que le pases como parametro y te devuelve un array con los resultados. Al mismo array podes agregarle paginación y todas las mañas que se te ocurra.

Dejo el código aquí debajo. Esta "extendido" para claridad, se puede escribir en muchas menos lineas.

module SearchHelper
  def buscador(clase, query)
    texto = query.split(" ")
    consulta = ""
    columnas = clase.constantize.columns
    cantidad = 0

    columnas.each do |columna| 
      texto.each do |palabra|           
        consulta += " or " if !consulta.empty? and columna.type == :string
        consulta += "#{columna.name} like ?" if columna.type == :string
        cantidad += 1 if columna.type == :string
      
      end      
    end
    
    texto.each do |palabra|
      palabra = "%#{palabra}%"
    end

    resultado = clase.constantize.where(consulta, *(texto * (cantidad / texto.size)))
    return resultado
  end
end

Salu2

PD: Para usarlo en rails simplemente crean un archivo que se llame search_helper.rb y pegan el código anterior. No es una obra de arte y seguramente puede optimizarse y mucho.

A.P. Nicolás Zuasti
@zonical.net/cv
Wild Dog Games

Nicolas Zuasti

unread,
Jul 24, 2012, 2:32:47 PM7/24/12
to p-s-f
def buscador(clase, query)
    texto = query.split(" ")
    consulta = ""
    columnas = clase.constantize.columns
    cantidad = 0

    columnas.each do |columna| 
      texto.each do |palabra|           
        consulta += " or " if !consulta.empty? and columna.type == :string
        consulta += "#{columna.name} like ?" if columna.type == :string
        cantidad += 1 if columna.type == :string
      
      end      
    end
    i = 0
    texto.each do |palabra|
      texto[i] = "%#{palabra}%"
      i += 1
    end

    resultado = clase.constantize.where(consulta, *(texto * (cantidad / texto.size)))
    return resultado
end

Mini correccion, estaba cambiando mal las variables dentro del arreglo de texto.

Para comodidad hice un initializer con el metodo, de esa forma puedo llamarlo desde modelos, controladores y vistas. Desde donde quiera.

Salu2

A.P. Nicolás Zuasti
@zonical.net/cv
Wild Dog Games



2012/7/24 Nicolas Zuasti <nicoz...@gmail.com>
Reply all
Reply to author
Forward
0 new messages