动态创建查询 - Rails 5

问题描述 投票:0回答:1

如果我手动编写查询,它就会像

User.where("name LIKE(?) OR desc LIKE(?)",'abc','abc')
    .where("name LIKE(?) OR desc LIKE(?)",'123','123')

但是,我需要动态生成该查询。我正在获取数据

def generate_query(the_query)

   query,keywords = the_query

   # Here 
   # query = "name LIKE(?) OR desc LIKE(?)"
   # keywords = [['abc','abc'],['123','123']]

   keywords.each do |keyword|
       users = User.where(query,*keyword) <-- not sure how to dynamically add more 'where' conditions.    
    end

end

我正在使用Rails 5.希望很清楚。任何帮助赞赏:)

ruby-on-rails activerecord rails-activerecord
1个回答
0
投票

像这样的东西:

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(AKA 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并非所有数据库都能理解)和LIKE模式中的%匹配任何字符序列。或者您可以在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')

所以你匹配所有关键字,而不是任何关键字。这可能是您的意图,也可能不是。

© www.soinside.com 2019 - 2024. All rights reserved.