类似这样:
q = User.where(a)
.where(b)
.where(c)
相当于:
q = User
q = q.where(a)
q = q.where(b)
q = q.where(c)
所以你可以写:
users = User
keywords.each do |keyword|
users = users.where(query, *keyword)
end
但任何时候你看到这种反馈模式(即对操作的结果应用一个操作,或
f(f( ... f(x)))
)你应该开始考虑
Enumerable#inject
(又名
Enumerable#reduce
):
users = keywords.inject(User) { |users, k| users.where(query, *k) }
也就是说,你的
query
有两个占位符,但
keywords
只是一个平面数组,因此您在中没有足够的值:
users.where(query, *k)
替换占位符。我认为您最好在此处使用命名占位符:
query = 'name like :k or desc like :k'
keywords = %w[abc 123]
users = keywords.inject(User) { |users, k| users.where(query, k: k) }
您可能还希望为您的
LIKE
因此:
query = "name like '%' || :k || '%' or desc like '%' || :k || '%'"
users = keywords.inject(User) { |users, k| users.where(query, k: k)
哪里
||
是标准的SQL字符串连接运算符(AFAIK并非所有数据库都理解),并且
%
以相似的模式匹配任何字符序列。或者,您可以在Ruby中添加模式匹配,避免担心数据库处理字符串串联的不同方式:
query = 'name like :k or desc like :k'
users = keywords.inject(User) { |users, k| users.where(query, k: "%#{k}%")
此外,这:
User.where("name LIKE(?) OR desc LIKE(?)",'abc','abc')
.where("name LIKE(?) OR desc LIKE(?)",'123','123')
生成
WHERE
条款如下:
where (name like 'abc' or desc like 'abc')
and (name like '123' or desc like '123')
所以你匹配了
全部的
关键字,而不是
任何
其中之一。这可能是你的意图,也可能不是。