5

ich ein paar ähnliche Fragen gefunden, während hier die Suche, aber wenn ich es sei denn, zu den Lösungen hinzuzufügen versucht, das ich gefunden, begannen die Dinge zu brechen ...Mehrere Abfragebedingungen in Rails - wenn sie existieren.

hier, was ich habe, das funktioniert:

Controller:

@metrics = Metric.where("current_ratio > ?", @screen.current_ratio_min) unless @screen.current_ratio_min.nil? 

Sobald ich eine andere .wo Zeile hinzufügen (von denen ich viele hinzufügen müssen),

@metrics = Metric.where("current_ratio > ?", @screen.current_ratio_min) unless @screen.current_ratio_min.nil? 
    .where("current_ratio < ?", @screen.current_ratio_max) unless @screen.current_ratio_max.nil? 

ich erhalte eine Fehlermeldung:

undefined method `where' for false:FalseClass 

Ich nehme an, dies ist, weil die erste, wenn meine Abfrage endet. Wie bewerbe ich mich, wenn nicht nur für jede einzelne Bedingung? Wenn das tatsächlich das Problem ist: \

Vielen Dank im Voraus!

+0

Im verwandten Abschnitt fand ich http://stackoverflow.com/questions/9308820/rails-searching-with-multiple-conditions-if-values-are-not-empty?rq=1, die mich Problem löst, denke ich ... Ich denke, wenn Sie nicht wissen, was Sie suchen müssen, ist es schwer zu finden, was y Du suchst! – jon

Antwort

7
@metrics = Metric.all 
@metrics = @metrics.where('current_ratio > ?', @screen.current_ration_min) if @screen.current_ratio_min.present? 
@metrics = @metrics.where('other_value > ?', @screen.other_value) if @screen.other_value.present? 

Dies ist der beste Weg, ich ohne programmatisch den Aufbau einer Zeichenkette, in der Klausel denken kann, die für SQL-Injection riskant sein kann.

Fügen Sie so viele Bedingungen hinzu, wie Sie möchten. Bemerkenswert, verwenden wenn etwas.präsentieren? statt deiner außer etwas.nil?

Auch die Metric.all ist möglicherweise nicht ideal, aber was auch immer Sie brauchen, um alle Aufzeichnungen anzufangen.

+3

Dies funktioniert nur in Schienen 4, in Schienen 3 führt alle die Abfrage aus und gibt ein Array zurück (Sie könnten stattdessen 'scoped' in Schienen 3 verwenden) –

+0

Vielen Dank! Das ist viel sauberer als das, was ich vorhatte. Und es sieht so aus, als wäre es noch besser skalierbar! Danke an alle, anscheinend war das ein komplizierteres Problem als ich dachte! Viele gute Ideen :) – jon

+0

In Rails4, Wie viele SQL-Auswahl wird ausgeführt? dreimal ? oder nur einmal? –

-1

Was ist mit so etwas?

if [email protected]_ratio_min.nil? && [email protected]_ratio_max.nil? 
    @metrics = Metric.where("current_ratio > ?", @screen.current_ratio_min).where("current_ratio < ?", @screen.current_ratio_max) 
elsif @screen.current_ratio_min.nil? && [email protected]_ratio_max.nil? 
    @metrics = Metric.where("current_ratio < ?", @screen.current_ratio_max) 
elsif [email protected]_ratio_min.nil? && @screen.current_ratio_max.nil? 
    @metrics = Metric.where("current_ratio > ?", @screen.current_ratio_min) 
else 
    @metrics = Metric.all 
end 
+0

Ich war nicht so klar wie ich hätte sein sollen. Es ist möglich, dass jemand einen Mindestwert eingibt, aber den Maximalwert leer lässt. In diesem Fall möchte ich nur einen Wert größer als min suchen. Wenn das Sinn macht. – jon

+0

Fügen Sie einfach weitere Bedingungen hinzu. Siehe aktualisierte Antwort. –

+0

Das wird sehr unordentlich, wenn er ein paar optionale Filter hat. –

-1

Versuchen Sie, mit dem folgenden Code

if @screen.current_ratio_min and @screen.current_ratio_max 
    @metrics = Metric.where("current_ratio > ? and current_ratio < ?", @screen.current_ratio_min, @screen.current_ratio_max) 
else 
unless @screen.current_ratio_min.blank? 
    @metrics = Metric.where("current_ratio > ?", @screen.current_ratio_min) 
else 
    unless @screen.current_ratio_max.blank? 
    @metrics = Metric.where("current_ratio < ?", @screen.current_ratio_max) 
    else 
    @metrics = Metric.all 
    end 
end 
end 
+1

Stellen Sie sich vor, wie dieser Code aussieht, wenn Sie einen weiteren optionalen Parameter hinzufügen. –

+0

Joel, es holt die begrenzten Aufzeichnungen gemäß der Bedingung. Wenn wir zuerst alle Datensätze abrufen, werden wir Bedingungen dafür anwenden, dh für jede Bedingung müssen wir zuerst alle Datensätze abrufen, die auf diese Weise optimiert werden können :). –

+0

Es stimmt, dass meine Option nicht als Abfrage optimiert ist, aber dieser Code wäre mit mehr Parametern nicht ausführbar. Wenn sie optimieren müssen, denke ich, dass sie die Abfrage programmatisch erstellen müssen. Ich würde nicht vorzeitig auf Kosten der Wartbarkeit des Codes optimieren. –

1

Wenn Sie sauberen Code möchten, verwenden Sie scope

In metric.rb

scope :current_ratio_min, lambda {|current_ratio_min| 
    current_ratio_min.present? ? where('current_ratio > ?', current_ration_min) : where()} 
    scope :current_ratio_max, lambda {|current_ratio_max| 
    current_ratio_max.present? ? where('current_ratio > ?', current_ratio_max) : where()} 

Ihre Suche:

@metrics = Metric.current_ratio_min(@screen.current_ratio_min).current_ratio_max(@screen.current_ratio_max)` 
0

Schreiben Sie die folgende Methode in der Klasse Array

class Array 
    def add_condition!(condition, conjunction = 'AND') 
    if String === condition 
    add_condition!([condition]) 
    elsif Hash === condition 
    add_condition!([condition.keys.map { |attr| "#{attr}=?" }.join(' AND ')] + condition.values) 
    elsif Array === condition 
    unless condition.empty? 
     self[0] = "(#{self[0]}) #{conjunction} (#{condition.shift})" unless empty? 
     self.push(*condition) 
    end 
    else 
    raise "don't know how to handle this condition type" 
    end 
    self 
end 
end 

Sie Ihre Bedingungen für Active bauen können, wo oder mit Bedingungen finden wie

conditions = [] 
conditions.add_condition!(["current_ratio > ?", @screen.current_ratio_min]) unless @screen.current_ratio_min.nil? 
conditions.add_condition!(["current_ratio < ?", @screen.current_ratio_max]) unless @screen.current_ratio_max.nil? 
@metrics = Metric.where(conditions) 

folgt Dies wird mit und/oder Kombinationen in den Aufbau mehrerer Bedingungen hilfreich sein

Verwandte Themen