Reputation: 1793
I have 3 tables: Objects
, Locations
, Hotels
.
Each object has several locations, and each location has several hotels (in 20 miles radius by default).
My models (a little bit simplified it to concentrate on the main things)
object.rb
attr_accessible :name
has_many :locations
has_many :hotels
location.rb
attr_accessible :name, :address, :longitude, :latitude
has_many :objects
has_many :hotels
hotels.rb
attr_accessible :name, :address, :longitude, :latitude
has_many :objects
has_many :locations
I want to create a search form, where user will be able to input Object's name, and search radius.
The output should be a list of all hotels, which are located within the given radius (less or equal to 20 miles) from the center of each location, which corresponds to object.
I want to use Geocoder's gem method near
, but I am not sure how to build the controller layer of such task.
Upvotes: 4
Views: 1028
Reputation: 5962
You want a spatial-query-engine in your db to do these queries, e.g. MongoDB or PostGIS (in Postgres). I think the answer you're looking for will vary depending on which one you're using. I use PostGIS for this stuff and really like it.
That said, Geocoder can be used to power this internally without a spatial-query-engine, though it will be not-so-efficient. It will grind to a halt if you get really big. If you look at the source: https://github.com/alexreisner/geocoder/blob/master/lib/geocoder/stores/active_record.rb
# skeleton for the controller method
obj = Object.find(name)
locations = obj.locations
near_hotels = locations.map do |loc|
locations.hotels.near([loc.latitude, loc.longitude])
end
not sure the near method properly takes a radius argument, but you could write your own pretty easily by basically copying it:
# on the hotel class
def nearby(lat, lon, radius)
options = self.send(:near_scope_options, lat, lon, radius, {})
select(options[:select]).where(options[:conditions]).
order(options[:order])
}
I strongly suggest you check out PostGIS.
Note, my example method produces a relation. You can narrow down your selection by scoping to just those hotels that match your object.
Upvotes: 3