我希望我的搜索允许多个输入。我的模型中有一个范围:
scope :by_description, lambda { |description| where('description LIKE ?', "%#{description}%") unless description.nil? }
目前,如果我搜索“abc,efg”,它将查找该字符串。如何修改我的范围以允许“abc,efg”搜索描述字段中具有“abc”或“efg”的任何记录?
答案 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
以删除前导和尾随空格inject
将where
子句的集合链接在一起,数组中的每个搜索字词都有一个我还没有尝试过,所以可能需要进行一些调整。但这种方法很合理。关键是你需要多个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个或多个表具有描述字段时)。