When you have objects in your database that hold latitude and longitude and you want to find others that are close to given coordinates you can use the Graticule gem.
Graticule
Graticule Show archive.org snapshot offers several methods to compute the distance between two geo-dated objects but fetching records from the database that are within a given radius of a location is a bit trickier:
def close_destinations(latitude, longitude)
distance_sql = Graticule::Distance::Spherical.to_sql(:latitude => latitude, :longitude => longitude, :units => :kilometers)
Destination.all(:conditions => [ "#{distance_sql} <= 10" ])
end
The above code will find every Destination
that is close to the given latitude and longitude: Using
to_sql
Show archive.org snapshot
will give you an SQL snippet to compute the distance from the given geo point on database level. Just use it to SELECT
(maybe using AS distance
) or to put into WHERE
conditions.
Note that above we computed the distance in kilometers; by default, Graticule uses miles. Also, though the Earth is not at a perfect sphere, spherical distance computation it is good enough in most cases.
ActiveRecord integration: ActsAsGeocodable
When dealing with geo data, you'd often use
acts_as_geocodable
Show archive.org snapshot
for your Rails applications. There you can just use your model's
upgraded find
Show archive.org snapshot
to achieve the same:
Destination.all(:within => 10, :origin => some_other_destination, :units => :kilometers)
The acts_as_geocodable
gem uses Graticule itself.
If your model is not using acts_as_geocodable using plain Graticule will just do the job.
Support from the database
- MySQL 5 has spatial support Show archive.org snapshot . This involves custom data types and funny SQL syntax.
- It also lets you index such columns for faster querying, unfortunately
SPATIAL
indexes are only available for MyISAM table at the moment. This means you might need to extract your geocode fields to another table for fast querying.