Edificio Record Attivo Condizioni in un array - metodo privato 'scan' chiamato errore
Domanda
Sto tentando di costruire un insieme di condizioni in modo dinamico utilizzando un array come suggerito nella prima risposta qui: Uno o più parametri nel modello di trovare condizioni con Ruby on Rails.Tuttavia mi sembra di fare qualcosa di sbagliato e non so se quello che sto cercando è fondamentalmente falsi o se sono semplicemente botching la mia sintassi.
Sto semplificando in una singola condizione qui per cercare di illustrare il problema, come ho cercato di costruire una semplice Prova di concetto, lungo queste linee di stratificazione su 5 condizioni diverse stili sto affrontando.
Questo funziona:
excluded.push 12
excluded.push 30
@allsites = Site.all(:conditions => ["id not in (?)", excluded])
Questo si traduce in un metodo privato 'scan' chiamato errore:
conditionsSet = []
excluded.push 12
excluded.push 30
conditionsSet << ["id not in (?)", excluded]
@allsites = Site.all(:conditions => conditionsSet)
Grazie per qualsiasi consiglio.Non ero sicuro se la cosa migliore era mettere questo come un elemento di follow-up per le relative domande/risposte che ho indicato all'inizio.Dal momento che ho un problema, non una risposta.Se c'è un modo migliore di questo post relativi al post esistente, per favore fatemelo sapere.
Soluzione
Prova questo:
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
Ora, da qualche parte nel vostro controller:
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
Ora, da qualche parte nel vostro controller:
Site.exclude_ids_by_name_and_state([1,2])).all
Site.exclude_ids_by_name_and_state(nil, "ABC").all
Altri suggerimenti
Si desidera:
conditionsSet += ["id not in (?)", excluded]
invece di:
conditionsSet << ["id not in (?)", excluded]
+=
aggiunge i due matrici insieme (pensare ad esso come l'unione di due in un array), mentre <<
inserisce un nuovo elemento in un array.In modo che si stanno ottenendo: [["id not in (?)", excluded]]
quando si utilizza <<
, e :conditions
vuole un array in cui questo primo elemento è una stringa, non un array).
Provare SmartTuple, progettato specificamente per casi come questo.
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")
Per me è anche preferibile utilizzare options
hash invece ordinato argomenti.Man mano che il progetto cresce, più condizioni possono apparire e si perde traccia di quale arriva che.Hash sembra e si comporta più chiara, più facilmente si può convalidare, per evitare gli errori del software.