Pregunta

Digamos que tengo un formulario donde los usuarios pueden buscar personas cuyo nombre comience con una cadena particular de name , por ejemplo, " Mi " encontraría '' Mike '' y "Miguel". Probablemente crearía una declaración de búsqueda como esta:

find(:all, :conditions => ['name LIKE ?', "#{name}%"])

Digamos que el formulario también tiene dos campos opcionales, hair_color y eye_color que se pueden usar para filtrar aún más los resultados. Ignorando la parte del nombre de la consulta, una declaración de búsqueda para personas que pueden tomar un número arbitrario de parámetros opcionales podría verse así:

find (: all,: condition = > {params [: person]})

Que para mis dos parámetros opcionales se comportaría como el equivalente de esto:

find (: all,: condition = > {: hair_color = > hair_color,: eye_color = > eye_color})

Lo que no puedo entender es cómo fusionar estos dos tipos de consultas donde el campo requerido, "nombre" se aplica a los "como" condición anterior, y los parámetros opcionales hair_color y eye_color (y quizás otros) se pueden agregar para filtrar aún más los resultados.

Ciertamente puedo construir una cadena de consulta para hacer esto, pero creo que debe haber una "vía de rieles". Eso es más elegante. ¿Cómo puedo fusionar parámetros obligatorios de enlace con parámetros opcionales?

¿Fue útil?

Solución

Este es el uso perfecto de un ámbito con nombre.

cree un ámbito con nombre en el modelo:

named_scope :with_name_like, lambda {|name|
  {:conditions => ['name LIKE ?', "#{name}%"]}
}

En este punto puedes llamar

Model.with_name_like("Mi").find(:all, :conditions => params[:person])

Y Rails fusionará las consultas por usted.

Editar: Código para Waseem:

Si el nombre es opcional, puede omitir el ámbito con nombre de su cadena de método con una condición if:

unless name.blank?
   Model.with_name_like("Mi").find(:all, :conditions => params[:person])
else
   Model.find(:all, :conditions => params[:person])
end

O podría redefinir el alcance nombrado para hacer lo mismo.

named_scope :with_name_like, lambda {|name|
  if name.blank?
    {}
  else
    {:conditions => ['name LIKE ?', "#{name}%"]}
  end
}

Update

Aquí está la versión Rails 3 del último fragmento de código:

scope :with_name_like, lambda {|name|
  if not name.blank?
    where('name LIKE ?', "#{name}%")
  end
}

Otros consejos

¿Para cumplir también con la solicitud de Waseem, pero dejando nulo en lugar de estar en blanco? (lo cual es falso en caso de que quiera usar " @things = Thing.named_like (params [: name]) " directamente)

named_scope :named_like, lambda do |*args| 
  if (name=args.first)
    {:conditions => ["name like ?",name]}
  else
    {}
  end
end

# or oneliner version:

named_scope :named_like, lambda{|*args| (name=args.first ? {:conditions => ["name like ?",name]} : {}) } }

Espero que ayude

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top