2009-06-09 7 views
0

Je souhaite créer une requête SQL dans une application Rails qui ajoute une condition lorsqu'un menu déroulant est ajouté. Évidemment, je ne veux pas chercher avec une condition vide si le menu déroulant n'est pas sélectionné. Comment puis-je développer une condition dynamique dans une instruction SQL?ActiveRecord prend-il en charge les conditions dynamiques dans les instructions SQL?

exemple non testé:

Lorsque la liste déroulante n'est pas sélectionnée: Object.find ("billy": conditions => {})

Lorsque la liste déroulante est sélectionnée: Object.find ("billy": conditions => { "last_name => "johnson"})

Merci pour vos commentaires!

+0

Remarque rapide, Ruby lui-même ne fait pas de SQL, vous vous posez des questions sur Rails, ActiveRecord en particulier :-) –

+1

Si vous utilisez ActiveRecord, Object n'est pas un bon nom pour un modèle, car il est l'un des classes de base en Ruby. Si vous optez pour générique, essayez Model ou Thing. # 2 - Thing.find ("billy",: conditions => {etc ..}) ne fonctionne pas non plus. Si vous avez en quelque sorte mis en place Thing pour avoir une colonne ID avec la valeur "billy", alors vous pouvez dire Thing.find ("billy"), pas besoin de conditions.Si vous utilisez des conditions, vous voulez généralement Thing.find: d'abord,: conditions => {etc ..} ou Thing.find: all,: conditions => {etc ..}. Vous trouverez ci-dessous quelques bonnes réponses qui ne fonctionneront pas en raison de ce problème. – austinfromboston

+0

@austinfromboston Je suis d'accord, mais j'ai le sentiment qu'il l'utilisait comme exemple, n'utilisant pas cette classe ... au moins, j'espère qu'il n'utilisera pas cette classe ... –

Répondre

1

Peut-être?

Object.find("billy", :conditions => last_name.nil? ? {} : {:last_name => last_name}) 
5

Vous ne savez pas exactement ce que vous faites, mais la manière générale d'y parvenir est d'avoir la valeur du menu déroulant (pas de texte visible) comme identifiant de l'objet que vous souhaitez sélectionner. Si vous ne disposez pas d'une sélection, vous pouvez utiliser quelque chose comme ceci:

last_name = unless params[:object][:last_name] 

conditions = [] 
conditions << "last_name = ?" unless last_name.blank? 
conditions << last_name unless last_name.blank? 

Object.find("billy", :conditions => conditions) 

Découvrez this link pour en savoir plus sur ActiveRecord::Base.find() méthodes et la bonne façon de les utiliser. Regardez également this great guide pour savoir comment vous protéger contre les attaques par injection SQL.

Édition 1: Code modifié pour être plus propre. Cette méthode a aussi l'avantage d'être capable d'ajouter facilement des conditions séparées, assurez-vous juste que vous ajoutez tous les "quelque chose =?" avant d'ajouter la valeur associée (param).

Éditer 2: Si vous n'avez pas vu le select form helper, vous pourriez envisager de l'utiliser pour votre liste déroulante. Rend la vie beaucoup plus facile :-)

+0

Je ne sais pas si j'ai volé " last_name =>? " de votre code ou adapté de la question. De toute façon ma relecture est nulle! Merci de l'avoir signalé. –

+0

Lol, nous avons probablement tous deux regardé le code original ... Je n'avais même pas remarqué que c'était faux là aussi. –

3

En supposant que votre #find est dans un contrôleur et que la valeur sélectionnée arrive en tant qu'élément dans params (et je pense que vous devriez envisager de changer les choses sinon!) Alors vous devriez être capable de faire quelque chose comme ceci:

if params[:last_name] # or whatever it's actually called 
    Object.find("billy," :conditions => {'last_name = ?', params[:last_name]}) 
else 
    Object.find("billy") 
end 

Si vous utilisez une version raisonnablement récente de ActiveRecord (2.1 devrait le faire, peut-être 2.0) alors vous pourriez changer cette logique jusqu'à un named_scope:

class Object < ActiveRecord::Base 
    named_scope :for_last_name, lambda { |nm| { :conditions => nm.nil? ? {} : { last_name => nm } } 

et puis votre contrôleur bout vers le bas (et nous aimons les contrôleurs minces)

Object.for_last_name(params[:last_name]) 

(non testé) Tout un peu

+0

He il, vous devez avoir regardé mon code et utilisé "last_name =>?" au lieu de "last_name =?". Désolé de vous jeter, j'ai réparé le mien :-) –

+0

D'accord sur l'utilisation de named_scopes lorsque vous essayez de gérer des conditions dynamiques – Scott

0

J'utilise SmartTuple pour cela. C'est simple, mais offre une approche systématique pour construire des «conditions conditionnelles».

Questions connexes