我试图在Rails 3中进行搜索。我有一个像这样的数据库对象,具有如下属性:
@food.fruit = "Apples, Pears, Plums"
我有一个使用复选框中的参数的搜索,如下所示:
params[:search] = ["Apples", "Oranges", "Bananas", "Grapefruit"]
由于上面的@food
对象有“苹果”而搜索数组中有“苹果”,我希望此搜索成功。但是我无法正常工作。
我最初的想法是做类似
的事情@results = Food.where("fruit LIKE ?", "%params[:search]%")
或
@results = Food.where("fruit IN ?", params[:search])
但是,如果params[:search]
仅包含@food.fruit
元素且没有其他元素,则第一个仅有效。第二个根本不起作用。
我的最后一个尝试是做
之类的事情@results = Array.new
params[:search].each do |search|
@results << Food.where("fruit LIKE ?", search)
end
但如果我不必这样做,我宁愿不这样做。有人有什么建议吗?
答案 0 :(得分:2)
你正在寻找的是像这样的SQL:
WHERE LOWER(fruit) LIKE '%apples%'
OR LOWER(fruit) LIKE '%oranges%'
OR LOWER(fruit) LIKE '%bananas%'
OR LOWER(fruit) LIKE '%grapefruit%'
请注意,LIKE
不一定不区分大小写,因此将所有内容推送到小写(或大写)通常是个好主意。
这很简单,但当您需要x.where(...).where(...)...
时,AND
会将条件与OR
联系起来。一种方法是将where
的第一个参数构建为字符串,方法是将"LOWER(fruit) LIKE ?"
字符串的正确数量粘贴在一起,以匹配params[:search]
中的元素数量:
@results = Food.where(
(["LOWER(fruit) LIKE ?"] * params[:search].length).join(' OR '),
*(params[:search].map { |s| '%' + s.downcase + '%' })
)
答案 1 :(得分:1)
基本上你正在进行5次单独的搜索。虽然制作5个单独的SQL查询可能不是答案,但您可以始终加入数组,例如:
scope :search_fruit, lambda {|*fruits|
where fruits.flatten.map {|fruit| arel_table[:fruit].matches("%#{fruit}%") }.inject(&:or)
}
和
Food.search_fruit(params[:fruit])