Bedingungen mit Bind-Variablen und optionale Parameter
-
10-07-2019 - |
Frage
Lassen Sie uns sagen, dass ich ein Formular, in dem Benutzer für Menschen, deren Namen suchen beginnt mit einer bestimmten Zeichenfolge name
, zum Beispiel „Mi“ finden würde „Mike“ und „Miguel“. Ich würde wahrscheinlich eine Such Aussage erstellen wie folgt:
find(:all, :conditions => ['name LIKE ?', "#{name}%"])
Lassen Sie uns sagen, dass die Form auch zwei optionale Felder hat, hair_color
und eye_color
, die verwendet werden können, um die Ergebnisse weiter zu filtern. Das Ignorieren des Namensteils der Abfrage, ein Fund Erklärung für Menschen, die in einer beliebigen Anzahl von optionalen Parametern nehmen könnte wie folgt aussehen:
find(:all, :conditions => { params[:person] })
Was für meine zwei optionale Parameter als Äquivalent dieses verhalten würde:
find(:all, :conditions => { :hair_color => hair_color, :eye_color => eye_color })
Was kann ich nicht herausfinden, wie diese beiden Arten von Abfragen zu verschmelzen, wo das erforderliche Feld „name“ angewandt wird die „wie“ Zustand über, und die optionalen hair_color
und eye_color
Parameter (und vielleicht auch andere) hinzugefügt werden, um die Ergebnisse weiter zu filtern.
Ich kann auf jeden Fall eine Abfrage-String, dies zu tun aufbauen, aber ich fühle es muss ein „Schienen Weg“ sein, die mehr elegant. Wie kann ich fusionieren zwingend binden Parameter mit optionalen Parametern?
Lösung
Dies ist die perfekte Verwendung eines benannten Umfangs.
Erstellen Sie eine benannte Umfang im Modell:
named_scope :with_name_like, lambda {|name|
{:conditions => ['name LIKE ?', "#{name}%"]}
}
An dieser Stelle können Sie anrufen
Model.with_name_like("Mi").find(:all, :conditions => params[:person])
Und Rails werden die Abfragen für Sie zusammenführen.
Edit: Code für Waseem:
Wenn der Name ist optional Sie könnten entweder den benannten Umfang von Ihrer Methode Kette mit einer, wenn der Bedingung weglassen:
unless name.blank?
Model.with_name_like("Mi").find(:all, :conditions => params[:person])
else
Model.find(:all, :conditions => params[:person])
end
Oder Sie könnten den benannten Rahmen neu zu definieren, das Gleiche zu tun.
named_scope :with_name_like, lambda {|name|
if name.blank?
{}
else
{:conditions => ['name LIKE ?', "#{name}%"]}
end
}
Aktualisieren
Hier ist der Rails 3-Version des letzten Code-Snippet:
scope :with_name_like, lambda {|name|
if not name.blank?
where('name LIKE ?', "#{name}%")
end
}
Andere Tipps
Zur Einhaltung auch mit Waseem Anfrage, aber erlaubt nil stattdessen leer? (Was im Falle udeful ist wollen Sie "@things = Thing.named_like (params [: Name])" verwenden, direkt)
named_scope :named_like, lambda do |*args|
if (name=args.first)
{:conditions => ["name like ?",name]}
else
{}
end
end
# or oneliner version:
named_scope :named_like, lambda{|*args| (name=args.first ? {:conditions => ["name like ?",name]} : {}) } }
Ich hoffe, es hilft