Rails,根据参数是否为零来应用范围

var*_*tis 8 scope ruby-on-rails ruby-on-rails-3

我已经多次遇到这个问题:我想在查询中应用范围,但前提是传递给范围的参数不是null.所以

tags = Tag.where(name: params[:name]) if params[:name]
Run Code Online (Sandbox Code Playgroud)

但是,这有两个问题.一个是Rails会立即评估查询,所以如果我想对它应用更多条件,比如说

tags.where(location: params[:place]) if params[:place]
Run Code Online (Sandbox Code Playgroud)

它将再次查询DB.第二个问题是它看起来不太好,我试图用类方法解决这个问题.

  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
Run Code Online (Sandbox Code Playgroud)

但是,我不能简单地放在all那里,因为它会评估查询.有什么想法吗?

MrY*_*iji 9

在这里你可以使用lambda范围,并使用selfto来调用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
Run Code Online (Sandbox Code Playgroud)

对于一个非常基本的范围,这需要太多行,这是压缩版本:

class Tab < ActiveRecord::Base

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

end
Run Code Online (Sandbox Code Playgroud)

也: