-
Alex Reisner authoredAlex Reisner authored
Geocoder¶ ↑
Geocoder is a complete geocoding solution for Ruby. With Rails it adds geocoding (by street or IP address), reverse geocoding (find street address based on given coordinates), and distance queries. It’s as simple as calling geocode
on your objects, and then using a scope like Venue.near("Billings, MT")
.
Compatibility¶ ↑
-
Supports multiple Ruby versions: Ruby 1.8.7, 1.9.2, and JRuby.
-
Supports multiple databases: MySQL, PostgreSQL, SQLite, and MongoDB (1.7.0 and higher).
-
Supports Rails 3. If you need to use it with Rails 2 please see the
rails2
branch (no longer maintained, limited feature set). -
Works very well outside of Rails but you’ll need to install either the
json
(for MRI) orjson_pure
(for JRuby) gem.
Install¶ ↑
As a Gem¶ ↑
Add to your Gemfile:
gem "geocoder"
and run at the command prompt:
bundle install
Or As a Plugin¶ ↑
At the command prompt:
rails plugin install git://github.com/alexreisner/geocoder.git
Configure Object Geocoding¶ ↑
In the below, note that addresses may be street or IP addresses.
ActiveRecord¶ ↑
Your model must have two attributes (database columns) for storing latitude and longitude coordinates. By default they should be called latitude
and longitude
but this can be changed (see “More on Configuration” below):
rails generate migration AddLatitudeAndLongitudeToModel latitude:float longitude:float rake db:migrate
For reverse geocoding your model must provide a method that returns an address. This can be a single attribute, but it can also be a method that returns a string assembled from different attributes (eg: city
, state
, and country
).
Next, your model must tell Geocoder which method returns your object’s geocodable address:
geocoded_by :full_street_address # can also be an IP address after_validation :geocode # auto-fetch coordinates
For reverse geocoding, tell Geocoder which attributes store latitude and longitude:
reverse_geocoded_by :lat, :lon after_validation :reverse_geocode # auto-fetch address
Mongoid¶ ↑
First, your model must have an array field for storing coordinates:
field :coordinates, :type => Array
You may also want an address field, like this:
field :address
but if you store address components (city, state, country, etc) in separate fields you can instead define a method called address
that combines them into a single string which will be used to query the geocoding service.
Once your fields are defined, include the Geocoder::Model::Mongoid
module and then call geocoded_by
:
include Geocoder::Model::Mongoid geocoded_by :address # can also be an IP address after_validation :geocode # auto-fetch coordinates
Reverse geocoding is similar:
include Geocoder::Model::Mongoid reverse_geocoded_by :coordinates after_validation :reverse_geocode # auto-fetch address
Bulk Geocoding¶ ↑
If you have just added geocoding to an existing application with a lot of objects you can use this Rake task to geocode them all:
rake geocode:all CLASS=YourModel
Geocoder will print warnings if you exceed the rate limit for your geocoding service.
Request Geocoding by IP Address¶ ↑
Geocoder adds a location
method to the standard Rack::Request
object so you can easily look up the location of any HTTP request by IP address. For example, in a Rails controller or a Sinatra app:
# returns Geocoder::Result object result = request.location
See “Advanced Geocoding” below for more information about Geocoder::Result objects.
Location-Aware Database Queries¶ ↑
To find objects by location, use the following scopes:
Venue.near('Omaha, NE, US', 20) # venues within 20 miles of Omaha Venue.near([40.71, 100.23], 20) # venues within 20 miles of a point Venue.geocoded # venues with coordinates Venue.not_geocoded # venues without coordinates
With geocoded objects you can do things like this:
obj.nearbys(30) # other objects within 30 miles obj.distance_from([40.714,-100.234]) # distance from arbitrary point to object obj.bearing_to("Paris, France") # direction from object to arbitrary point
Some utility methods are also available:
# look up coordinates of some location (like searching Google Maps) Geocoder.coordinates("25 Main St, Cooperstown, NY") => [42.700149, -74.922767] # distance (in miles) between Eiffel Tower and Empire State Building Geocoder::Calculations.distance_between([47.858205,2.294359], [40.748433,-73.985655]) => 3619.77359999382 # find the geographic center (aka center of gravity) of objects or points Geocoder::Calculations.geographic_center([city1, city2, [40.22,-73.99], city4]) => [35.14968, -90.048929]
Please see the code for more methods and detailed information about arguments (eg, working with kilometers).