I have a field where I'm using Jquery TokenInput to autocomplete a Product. To find the products I'm doing:
def token
@products = Product.order(:name)
respond_to do |format|
format.html
format.json { render json: @products.where("name ILIKE ?", "%#{params[:q]}%").limit(10).order('name DESC') }
end
end
If I have a product named Rice
and do a search on the field, typing in "r", "ri", and "ric", I want the closest result to be the one that matches the query. Instead though, if I have over 10 different types of Rices in the database, the results will be "out of order" with Rice
being placed around 6th or 9th place out of 10 founded rices. To me, Rice should come first and than Rice Ball or Cake but instead I get something like:
Brown Rice # First result in Tokeninput
Rice Cake
Yellow Rice
Long Grain Rice
Rice Ball
Chinese Rice
Super Rice
Rice
New Rice
The Super Rice Game
Even if I type in "Rice" exactly I get something similar to the above. I want it to be the 1st choice if r, ri, ric or rice
is typed in but my results don't believe in order, they only want chaos. How would this be done?
You may add the following method to your Product
model:
def self.good_search(criteria)
regexp = /#{criteria}/i; # case-insensitive regexp based on your string
result = order(:name).where("name ILIKE ?", "%#{criteria}%").limit(10)
result.sort{|x, y| (x =~ regexp) <=> (y =~ regexp) }
end
Here I use the match operator (=~) which returns position where regexp matched. The earlier the "rice" met the closer to the top of result array string'll be. This method might not be good for big arrays, but for 10 elements it's okay.
And here's your controller:
def token
respond_to do |format|
format.html
format.json { render json: Product.good_search(params[:q]) }
end
end
Good luck!