开发者

Rails 3 Searching through a string using an array

开发者 https://www.devze.com 2023-03-27 07:45 出处:网络
I am attempting to do a search in Rails 3 like so.I have a database object like so with an attribute like so:

I am attempting to do a search in Rails 3 like so. I have a database object like so with an attribute like so:

@food.fruit = "Apples, Pears, Plums"

and I have a search that u开发者_如何学JAVAses params from a checkbox, like so:

params[:search] = ["Apples", "Oranges", "Bananas", "Grapefruit"]

Since my @food object above has "Apples" and the search array has "Apples" I'd like for this search to be successful. However I am having trouble having this work properly.

My initial thought was to do something like

@results = Food.where("fruit LIKE ?", "%params[:search]%")

or

@results = Food.where("fruit IN ?", params[:search])

But the first only works if the params[:search] contains ONLY the @food.fruit elements and no others. The second doesn't work at all.

My last ditch resort is to do something like

@results = Array.new
params[:search].each do |search|
  @results << Food.where("fruit LIKE ?", search)
end

but I'd rather not do that if I don't have to. Anyone have any advice?


What you're looking for is some SQL like this:

WHERE LOWER(fruit) LIKE '%apples%'
   OR LOWER(fruit) LIKE '%oranges%'
   OR LOWER(fruit) LIKE '%bananas%'
   OR LOWER(fruit) LIKE '%grapefruit%'

Note that LIKE is not necessarily case insensitive so pushing everything to lower case (or upper case) is generally a good idea.

That's simple enough but saying x.where(...).where(...)... connects the conditions with AND when you want OR. One way is to build the first argument to where as a string by pasting together the right number of "LOWER(fruit) LIKE ?" strings to match the number of elements in params[:search]:

@results = Food.where(
    (["LOWER(fruit) LIKE ?"] * params[:search].length).join(' OR '),
    *(params[:search].map { |s| '%' + s.downcase + '%' })
)


Essentially you're doing 5 separate searches. While making 5 separate SQL queries might not be the answer, you could always join the array, like:

scope :search_fruit, lambda {|*fruits|
  where fruits.flatten.map {|fruit| arel_table[:fruit].matches("%#{fruit}%") }.inject(&:or)
}

and

Food.search_fruit(params[:fruit])
0

精彩评论

暂无评论...
验证码 换一张
取 消