Pregunta

Estoy intentando crear un conjunto de condiciones dinámicamente usando una matriz como se sugiere en la primera respuesta aquí: Uno o más parámetros en el modelo encuentran condiciones con Ruby on Rails.Sin embargo, parece que estoy haciendo algo incorrectamente y no estoy seguro de si lo que estoy intentando es fundamentalmente incorrecto o si simplemente estoy fallando en mi sintaxis.

Estoy simplificando a una sola condición aquí para tratar de ilustrar el problema, ya que he intentado construir una prueba de concepto simple siguiendo estas líneas antes de superponer los 5 estilos de condición diferentes con los que estoy lidiando.

Esto funciona:

excluded.push 12
excluded.push 30
@allsites = Site.all(:conditions => ["id not in (?)", excluded])

Esto da como resultado un método privado de 'escaneo' llamado error:

conditionsSet = []
excluded.push 12
excluded.push 30
conditionsSet << ["id not in (?)", excluded]
@allsites = Site.all(:conditions => conditionsSet)

Gracias por cualquier consejo.No estaba seguro de si lo correcto era poner esto como un elemento de seguimiento de las preguntas/respuestas relacionadas que anoté en la parte superior.Ya que tengo un problema, no una respuesta.Si hay una mejor manera de publicar esto relacionado con la publicación existente, hágamelo saber.

¿Fue útil?

Solución

Prueba esto:

Rails 2.3

class Site < ActiveRecord::Base

  def self.build_conditions(ids, name=nil, state=nil)
     cond = []
     cond << send(:sanitize_sql_array, ["id NOT IN (?)", ids]) unless ids.empty?
     cond << send(:sanitize_sql_array, ["name = ? ", name]) unless name
     cond << send(:sanitize_sql_array, ["state = ? ", state]) unless state
     cond.join(" and ")
  end    
end

Ahora en algún lugar de su controlador:

Site.all(:conditions => Site.build_conditions([1,2])) 
Site.all(:conditions => Site.build_conditions(nil, "ABC"))

Carriles 3

class Site < ActiveRecord::Base          
  def self.exclude_ids_by_name_and_state(ids, name=nil, state=nil)
    result = scoped
    result = result.where("id NOT IN (?)", ids) if ids.present?
    result = result.where(:name => name) if name.present?
    result = result.where(:state => state) if state.present?
    result
  end    
end

Ahora en algún lugar de su controlador:

Site.exclude_ids_by_name_and_state([1,2])).all 
Site.exclude_ids_by_name_and_state(nil, "ABC").all

Otros consejos

¿Quieres:

conditionsSet += ["id not in (?)", excluded]

en lugar de:

conditionsSet << ["id not in (?)", excluded]

+= añade las dos matrices conjuntamente (pensar en ella como la fusión de los dos en un array), mientras que << empuja un nuevo elemento en la matriz. Por lo que está recibiendo:. [["id not in (?)", excluded]] cuando se utiliza << y :conditions quiere una matriz en donde este primer elemento es una cadena (no una matriz)

Trate SmartTuple , que está diseñado específicamente para casos como este.

def self.build_conditions(options = {})
  [
    SmartTuple.new(" AND "),
    (["id NOT IN (?)", ids] if options[:ids].present?),
    ({:name => options[:name]} if options[:name].present?),
    ({:state => options[:state]} if options[:state].present?),
  ].sum.compile
end

...

Site.all(:conditions => Site.build_conditions(:ids => {1,2]))
Site.all(:conditions => Site.build_conditions(:name => "abc", :state => "disabled")

Para mí es también preferible para el uso de hash options en lugar de argumentos ordenados. A medida que el proyecto crece, más condiciones pueden aparecer y se le pierde la pista de los cuales proviene el que. miradas de patata y se comporta más clara además de que puede validar fácilmente para evitar errores de software.

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