我有一个搜索字段,用户可以在其中输入“ Param1”,并且我的控制器包含:
Model.where('column_name LIKE ?', "%#{search_field}%")
这将转换为:
SELECT ... FROM table WHERE column_name LIKE '%Param1%'
如果用户输入“ Param1”,但我希望将其用逗号分隔的搜索字段,则此方法很好。
因此,如果用户输入“ Param1,param2”或“ Param1,Param2,Param3”,WHERE LIKE子句应该起作用,我的想法是基于','拆分字符串,并且完全不知道如何构建这里有Model.where子句,因为它可以是1个参数或4个参数。
答案 0 :(得分:2)
这是我在一个项目上要做的:
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
答案 1 :(得分:2)
答案使用与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)
答案 2 :(得分:2)
如果您使用的是PostgreSQL,则可以使用ANY传递映射的参数数组:
Model.where('name LIKE ANY(array[?])', params.split(',').map { |val| "%#{val}%" })
# SELECT "models".*
# FROM "models"
# WHERE (name LIKE ANY(array['%param1%','%param2%']))
答案 3 :(得分:1)
拆分参数是个好主意。
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
应该工作。