5

ここで検索しているときに、私はいくつかの同様の質問を見つけましたが、私は私が見つけた解決策にしない限り、追加しようとしたとき、物事が壊れ始めた...Rails内の複数のクエリ条件 - 存在する場合。

は、ここで私が持っているものです動作する:

コントローラ:

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

私はエラーを取得する

@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? 

、(私は多くを追加する必要があるの)別の.where行を追加すると:

undefined method `where' for false:FalseClass 

これは、最初のクエリが終了しない限り、これは仮定しています。個々の状態だけでなく、どのように私を応募すればよいですか?それが実際問題であれば、\

ありがとうございます!

+0

関連するセクションでは、私が考える問題を解決するhttp://stackoverflow.com/questions/9308820/rails-searching-with-multiple-conditions-if-values-are-not-empty?rq=1が見つかりました...あなたは何を探したらいいのか分からなければ、何を見つけるのは難しいでしょうお探しですか? – jon

答えて

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? 

これは私がプログラムでSQLインジェクションのために危険なことができWHERE句の文字列を構築することなく、考えることができる最高の方法です。

必要な条件を追加してください。注目すべきは、もし何か?あなたの代わりに何かをしないでください。

また、Metric.allは理想的ではないかもしれませんが、すべてのレコードを開始するために必要なものは何でも構いません。

+3

これはレール4のみで動作し、レール3はすべてクエリを実行して配列を返します(レール3では 'scoped'を使用できます) –

+0

ありがとうございました!これは私が思っていたよりもはるかにクリーンです。そして、よりスケーラブルにブートするように見えます!みんなのおかげで、これは明らかに私が思ったよりも複雑な問題でした!素晴らしいアイディアがたくさんあります:) – jon

+0

Rails4では、いくつのSQL selectが実行されますか? 3回 ?または1回だけ? –

-1

このようなものはどうですか?

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

私ははっきりとしたものではありませんでした。誰かが最小値を入れても、最大値を空白のままにすることは可能です。その場合、私はちょうど最小値以上を検索したい。それが意味をなさないならば。 – jon

+0

条件を追加するだけです。更新された回答をご覧ください。 –

+0

これはいくつかのオプションのフィルタを持っていると非常に面倒です。 –

-1

metric.rbでscope

を使用し、次のコード

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

もう1つのオプションのパラメータを追加すると、このコードの外観を想像してみてください。 –

+0

ジョエル、それは条件ごとに限られたレコードをフェッチしています。最初にすべてのレコードを取得してから条件を適用すると、各条件ごとに、すべてのレコードを最初にフェッチする必要があります。この方法で最適化することができます:) –

+0

私のオプションはクエリに最適化されていないのですが、このコードはより多くのパラメータで実行できません。彼らが最適化する必要がある場合は、プログラムでクエリを構築する必要があると思います。コードのメンテナンス性を犠牲にしながら、早期に最適化するつもりはありません。 –

1

あなたはクリーンなコードが必要な場合にお試しください

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()} 

あなたのクエリ:

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

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) 

これは、AND/ORの組み合わせ

で複数の条件を構築する上で参考になりますが、次のようにあなたはActiveRecordのためのあなたの条件をビルドする場所や条件を見つけることができます

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 

あなたArrayクラスに次のメソッドを書きます

関連する問題