I have a Rails search form that performs a dynamic query. That is, the user enters a search like:
(hobby="skiing") OR (gender="male" AND hobby="jogging")
So, I don't know how many queries I will be searching by until runtime.
I parse the search query by converting it into a valid SQL query, so the above search would be converted to the following format:
query = "hobby LIKE ? OR (gender LIKE ? AND hobby LIKE ?)"
queries = ["skiing", "male", "jogging"]
For the following query:
where(query, queries)
However, the general syntax of the Rails search query is very limiting:
where(query, query_1, query_2, query_3)
I cannot replace the 'query_n' arguments with an array like I want to, without Rails throwing an error.
NoMethodError (undefined method `where' for ["a", "b", "c"]:Array)
Attempting to splat the array yields the same error:
where(query, *queries)
Again:
NoMethodError (undefined method `where' for ["a", "b", "c"]:Array)
So what can I do?
EDIT:
The full search function looks like this:
def self.search(search)
query = "%#{search}%"
if search
includes(:games, :jobs)
strngs = ["hobby = ? OR name = ? OR gender = ?", "dsfgdsfg", "dsgsdfgsd", "sdfsfsdf"]
.where(strngs)
What you'll want to do is pass an array as a single argument to where
which contains both the query AND the dynamic values. For example:
where(["att_1 LIKE ? OR att_2 LIKE ?", "value1", "value2"])
If an array is passed as the first and only argument, then the first element of the array is treated as a template. The following array values are treated as the dynamic values for the query template.
For your example, instead of having two separate variables queries
and query
, combine them into one query
variable:
# A single array with the query AND values
query = ["hobby LIKE ? OR (gender LIKE ? AND hobby LIKE ?)", "skiing", "male", "jogging"]
# Run the `where` with a single array as the argument
YourModel.where(query)
This will allow you to query the DB with an unknown number of values using LIKE
.
For reference: Rails where() docs