How to find the three best matches for a model search in Ruby on Rails?
I'm building a dog finder to help people choose the best dog breed for their lifestyle.
So I have created the Dog using Scaffold (could we say have I created a Dog model then?)
class CreateDogs < ActiveRecord::Migration
def self.up
create_table :dogs do |t|
t.string :breed
t.integer :speed
t.integer :size
t.integer :friendly
t.timestamps
end
end
end
speed
is rated from 1-10 with 10 being fastest.size
is rated 1-10 with 10 being heaviest.friendly
is rated 1-10 with 10 being friendliest.
The breed: Golden Lab for instance has a score
- speed = 5
- size = 8
- friendly = 10
I'm creating a form for users to fill in the range of attributes they are looking for, so they looking for a
- speed = 10
- size = 5
- friendly = 10
How would I return the top three breed matches for their search terms, using Ruby on Rails?
I've been looking at the <=>
operator, sort_by
, but I'm not sure how to string it all together. I thought it was a simple search at first - but all items need to be compared with each other.
Also, how could I to add weighting to friendliness, so it's more important than the other two attributes in terms of dog selection?
I'm new to Ruby on Rails, so excuse me if I use incor开发者_如何转开发rect terms.
You can calculate the difference between the queried and the actual value and get the absolute value (ie. make all negative numbers positive) to see how close the wish is to reality:
abs(wanted_speed - speed)
abs(wanted_size - size)
abs(wanted_friendly - friendly)
Then sum up these differences to see how much the queried values differ from the actual values of each dog.
To put weight on any attribute just multiply it with some value before sum up.
Maybe this is working:
@dogs = Dog.all(
:order => ["ABS(speed - ?) + ABS(size - ?) + (ABS(friendly - ?) * 3)",
params[:speed], params[:size], params[:friendly]],
:limit => 3)
For the weight you could also add variables in your form (eg. important = 3, don't care = 2, not important at all = 1) and add these to the query instead of the hardcoded 3
.
@dogs = Dog.all(:limit => 3, :order => "speed + size + friendly DESC")
If you would add weighting, you can add multipliers, like this would weight friendlyness double and size triple:
@dogs = Dog.all(:limit => 3, :order => "speed + (3 * size) + (2 * friendly) DESC")
精彩评论