Rails用逗号分隔搜索范围

时间:2014-09-29 21:55:39

标签: ruby-on-rails ruby-on-rails-3 search sqlite

我希望我的搜索允许多个输入。我的模型中有一个范围:

scope :by_description, lambda { |description| where('description LIKE ?', "%#{description}%") unless description.nil? }

目前,如果我搜索“abc,efg”,它将查找该字符串。如何修改我的范围以允许“abc,efg”搜索描述字段中具有“abc”或“efg”的任何记录?

3 个答案:

答案 0 :(得分:2)

这样的事情(基于其他答案):

  scope :by_description, ->(desc=nil) {
    if desc.blank?
      all
    else
      terms = desc.split(/\s*,\s*/).map { |t| t.strip }.map { |t| "%#{t}%" }
      where( ( ["#{table_name}.description like ?"] * terms.count).join(' or '), *terms )
    end
  }

答案 1 :(得分:1)

试试这个:

scope :by_description, lambda { |description|
    description.split(",").
    map(&:strip).
    inject(self) { |memo, term|
        memo.where("description like ?", term)
    }
    unless description.nil?
}

这是做什么的:

  • 获取传入的字符串并将其拆分为逗号分隔字符串数组
  • 在每个字符串上调用strip以删除前导和尾随空格
  • 使用injectwhere子句的集合链接在一起,数组中的每个搜索字词都有一个

我还没有尝试过,所以可能需要进行一些调整。但这种方法很合理。关键是你需要多个WHERE条款来获得"和"你正在寻找的行为。

答案 2 :(得分:1)

这是基于Todd的回答:

scope :by_description, ->(desc=nil) {
    if desc.present?
        desc.split(",").map(&:strip).inject(self) do |memo, term|
            memo.where("#{table_name}.description LIKE ?", "%#{term}%")
        end
    else
        all # or none, if you want no results returned      
    end
}

逻辑方面基本相同,但我使用了stabby语法,并确保范围始终返回可链接的东西。我也希望安全并将table_name添加到手动构建的查询中,以防止出现模糊的表错误(当2个或多个表具有描述字段时)。