Construire Conditions Active Record dans un tableau - « scan » méthode privée appelée erreur
Question
Je tente de construire un ensemble de conditions dynamiquement en utilisant un tableau comme suggéré dans la première réponse ici: Un params ou plus dans le modèle trouvent des conditions avec Ruby on rails . Cependant, je semble faire quelque chose de manière incorrecte et je ne sais pas si ce que je suis en train est fondamentalement saine ou si je suis simplement bousiller ma syntaxe.
Je simplifie vers le bas à une seule condition ici pour essayer d'illustrer la question comme je l'ai essayé de construire une preuve simple concept le long de ces lignes avant la superposition des 5 différents styles de condition que je suis contestait avec.
Cela fonctionne:
excluded.push 12
excluded.push 30
@allsites = Site.all(:conditions => ["id not in (?)", excluded])
Il en résulte une méthode privée 'scan' appelée erreur:
conditionsSet = []
excluded.push 12
excluded.push 30
conditionsSet << ["id not in (?)", excluded]
@allsites = Site.all(:conditions => conditionsSet)
Merci pour tout conseil. Je ne sais pas si la bonne chose était de mettre cela comme un élément de suivi à la question / réponses connexes je l'ai noté en haut. Depuis que j'ai un problème pas une réponse. S'il y a une meilleure façon d'afficher ce lié au poste existant s'il vous plaît laissez-moi savoir.
La solution
Essayez ceci:
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
quelque part dans votre contrôleur:
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
quelque part dans votre contrôleur:
Site.exclude_ids_by_name_and_state([1,2])).all
Site.exclude_ids_by_name_and_state(nil, "ABC").all
Autres conseils
Vous voulez:
conditionsSet += ["id not in (?)", excluded]
au lieu de:
conditionsSet << ["id not in (?)", excluded]
+=
ajoute les deux réseaux ensemble (le considérer comme fusionnant les deux dans une rangée), tandis que <<
pousse un nouvel élément sur le réseau. Donc, vous obtenez:. [["id not in (?)", excluded]]
lors de l'utilisation <<
et :conditions
veut un tableau où ce premier élément est une chaîne (pas un tableau)
SmartTuple , il a été conçu spécifiquement pour les cas comme celui-ci.
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")
Pour moi, il est également préférable d'utiliser hachage options
au lieu des arguments ordonnés. À mesure que votre projet se développe, plus les conditions peuvent apparaître et vous perdre de vue ce qui vient qui. Hash ressemble et se comporte plus clair, plus vous pouvez facilement le valider pour éviter les erreurs logicielles.