Rails动态'Where'子句

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

我有一个搜索字段,用户可以在其中输入“ Param1”,并且我的控制器包含:

Model.where('column_name LIKE ?', "%#{search_field}%")

这被转换为:

SELECT ... FROM table WHERE column_name LIKE '%Param1%'

如果用户输入“ Param1”,但我想用逗号分隔的搜索字段,则可以正常工作。

因此,如果用户输入“ Param1,param2”或“ Param1,Param2,Param3”,WHERE LIKE子句应该起作用,我的想法是基于','拆分字符串,并且完全不知道如何构建模型.where子句,因为它可以是1个参数或4。

sql ruby-on-rails ruby ruby-on-rails-5
4个回答
1
投票

这是我在一个项目上所做的:

values = search_field.split(',').map { |x| "%#{x}%" } # split values and add "%...%"
count = values.count # count them

# create an array of LIKE operators depending on the values counted
# if count is 2 then it will be an array: ['column_name LIKE ?', 'column_name LIKE ?']
where_sql_arr = count.times.map{'column_name LIKE ?'} 

# create the sql query joining with " OR "
# 'column_name LIKE ? OR column_name LIKE ?'
where_sql = where_sql_arr.join(' OR ') 

Model.where(where_sql, *values) # note the * before "values" to split the array into multiple arguments

0
投票

答案使用与answer of arieljuod相同的方法,但使用Arel API而不是使用纯字符串。

values = search_field.split(',')
column_name = Model.arel_table[:column_name]
query = values.map { |value| column_name.matches("%#{value}%") }.reduce(:or)
Model.where(query)

0
投票

如果使用的是PostgreSQL,则可以使用ANY传递映射的参数数组:

Model.where('name LIKE ANY(array[?])', params.split(',').map { |val| "%#{val}%" })
# SELECT "models".*
# FROM "models"
# WHERE (name LIKE ANY(array['%param1%','%param2%']))

0
投票

拆分参数是个好主意。

conditions = "Param1,Param2,Param3, Param4".gsub(" ","").split(',')

如果不使用掩码或正则表达式进行搜索就足够了,则可以使用IN查询或AR:Model.where(column_name: conditions)

否则(至少在PostgreSQL中,代码变得稍微复杂一些。

根据输入字符串构造查询字符串:

conditions = "Param1,Param2,Param3, Param4".gsub(" ","").split(',')

query = ("column_name ~* ? OR " * conditions.size)[0...-3] # Delete last unterminated " OR"

最后

Model.where(query, *conditions) # splat operator (*) converts array into argument list

应该工作。

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