Ilya Cherevkov
Ilya Cherevkov

Reputation: 1793

Search for hotels within a given radius for corresponding objects' locations (Gem Geocoder)

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.

enter image description here

Upvotes: 4

Views: 1028

Answers (1)

John Hinnegan
John Hinnegan

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

Related Questions