Pergunta

Estou tentando construir um conjunto de condições dinamicamente usando uma matriz, conforme sugerido na primeira resposta aqui: Um ou mais parâmetros no modelo encontram condições com rubi nos trilhos. No entanto, pareço estar fazendo algo incorretamente e não tenho certeza se o que estou tentando é fundamentalmente doentia ou se estou simplesmente estragado minha sintaxe.

Estou simplificando para uma única condição aqui para tentar ilustrar o problema, pois tentei criar uma prova simples de conceito nesse sentido antes de colocar os 5 estilos de condição diferentes com os quais estou disputando.

Isso funciona:

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

Isso resulta em um método privado 'Scan' chamado Erro:

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

Obrigado por qualquer conselho. Eu não tinha certeza se a coisa correta era colocar isso como um item de acompanhamento na pergunta/respostas relacionadas que observei no topo. Já que tenho um problema, não uma resposta. Se houver uma maneira melhor de postar isso relacionado à postagem existente, entre em contato.

Foi útil?

Solução

Experimente isso:

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

Agora em algum lugar do seu controlador:

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

Rails 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

Agora em algum lugar do seu controlador:

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

Outras dicas

Você quer:

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

ao invés de:

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

+= adiciona as duas matrizes (pense nisso como fusão dos dois em uma matriz) enquanto << empurra um novo elemento para a matriz. Então você está recebendo: [["id not in (?)", excluded]] Ao usar <<, e :conditions quer uma matriz em que este primeiro elemento é uma string (não uma matriz).

Tentar SmartTuple, ele foi projetado especificamente 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 mim, também é preferível usar options hash em vez de argumentos ordenados. À medida que seu projeto cresce, mais condições podem aparecer e você perderá a noção dos quais. A aparência de hash e se comporta mais clara e você pode validá -lo facilmente para evitar erros de software.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top