9

この問題に何度か遭遇しました。クエリにスコープを適用したいのですが、スコープに渡されたパラメーターが null でない場合に限ります。そう

tags = Tag.where(name: params[:name]) if params[:name]

ただし、これには 2 つの問題があります。1 つは、Rails がクエリをすぐに評価するため、さらに条件を適用したい場合は、

tags.where(location: params[:place]) if params[:place]

DBに再度クエリを実行します。2 番目の問題は、見栄えがよくないことです。これは、クラス メソッドで回避しようとしました。

  class Tag < ActiveRecord::Base
    def self.name_like this_name
      if !this_name.blank?
        where("name ILIKE '%#{this_name}%'")
      else
        #what do I put here? `all` does not work
      end
    end
  end

allただし、クエリを評価するため、単純にそこに入れることはできません。何かご意見は?

4

2 に答える 2

9

ここでは、ラムダ スコープを使用し、 を使用してselfを呼び出すことができself.allます。

  class Tag < ActiveRecord::Base

    scope :named_like, (lambda do |name| 
      if name.present?
        where("name ILIKE ?", "%#{name}%")
      else
        scoped # does not apply a where clause
      end
    end)

  end

これは非常に基本的なスコープに対して行数が多すぎます。圧縮されたバージョンは次のとおりです。

class Tab < ActiveRecord::Base

  scope :named_like, lambda{ |name| self.where("name ILIKE ?", "%#{name}%") if name.present? }

end

また:

于 2013-02-26T19:06:59.067 に答える
0

私が知っていること (およびここに書かれていること: ActiveRecord::Relation ) については、結果を反復処理する場合にのみクエリが実際に実行されます。したがって、次のように書くと:

tags = Tags.where(name: params[:name])
# other stuff here
tags = tags.where(location: params[:place])

このスニペットでは、クエリは実行されません。

tags.each { # do something }

しかし、そこにあります!もちろん一度だけ。
そもそもタグは ActiveRecord::Relation オブジェクトなので、where好きなだけ連鎖できます。

于 2013-02-26T21:24:48.913 に答える