Skip to content
Snippets Groups Projects
Select Git revision
  • master default protected
  • rails-geocoder
  • rails2
  • v1.5.1
  • v1.5.0
  • v1.4.9
  • v1.4.8
  • v1.4.7
  • v1.4.6
  • v1.4.5
  • remove
  • v1.4.4
  • v1.4.3
  • v1.4.2
  • v1.4.1
  • v1.4.0
  • v1.3.7
  • v1.3.6
  • v1.3.5
  • v1.3.4
  • v1.3.3
  • v1.3.2
  • v1.3.1
23 results

README.md

Blame
  • README.md 34.07 KiB

    Geocoder

    A complete geocoding solution for Ruby.

    Gem Version Code Climate Build Status GitHub Issues License

    Key features:

    • Forward and reverse geocoding, and IP address geocoding.
    • Connects to more than 40 APIs worldwide.
    • Performance-enhancing features like caching.
    • Advanced configuration allows different parameters and APIs to be used in different conditions.
    • Integrates with ActiveRecord and Mongoid.
    • Basic geospatial queries: search within radius (or rectangle, or ring).

    Compatibility:

    • Supports multiple Ruby versions: Ruby 2.x, and JRuby.
    • Supports multiple databases: MySQL, PostgreSQL, SQLite, and MongoDB (1.7.0 and higher).
    • Supports Rails 3, 4, and 5. 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, you just need to install either the json (for MRI) or json_pure (for JRuby) gem.

    Table of Contents

    Basic Features:

    Advanced Features:

    The Rest:

    See Also:

    Basic Search

    In its simplest form, Geocoder takes an address and searches for its latitude/longitude coordinates:

    results = Geocoder.search("Paris")
    results.first.coordinates
    => [48.856614, 2.3522219]  # latitude and longitude

    The reverse is possible too. Given coordinates, it finds an address:

    results = Geocoder.search([48.856614, 2.3522219])
    results.first.address
    => "Hôtel de Ville, 75004 Paris, France"

    You can also look up the location of an IP addresses:

    results = Geocoder.search("172.56.21.89")
    results.first.coordinates
    => [30.267153, -97.7430608]
    results.first.country
    => "United States"

    The success and accuracy of geocoding depends entirely on the API being used to do these lookups. Most queries work fairly well with the default configuration, but every application has different needs and every API has its particular strengths and weaknesses. If you need better coverage for your application you'll want to get familiar with the large number of supported APIs, listed in the API Guide.

    Geocoding Objects

    To automatically geocode your objects:

    1. Your model must provide a method that returns an address to geocode. 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). For example, if your model has street, city, state, and country attributes you might do something like this:

    def address
      [street, city, state, country].compact.join(', ')
    end

    2. Your model must have a way to store latitude/longitude coordinates. With ActiveRecord, add two attributes/columns (of type float or decimal) called latitude and longitude. For MongoDB, use a single field (of type Array) called coordinates (i.e., field :coordinates, type: Array). (See Advanced Model Configuration for using different attribute names.)

    3. In your model, tell geocoder where to find the object's address:

    geocoded_by :address

    This adds a geocode method which you can invoke via callback:

    after_validation :geocode

    Reverse geocoding (given lat/lon coordinates, find an address) is similar:

    reverse_geocoded_by :latitude, :longitude
    after_validation :reverse_geocode

    With any geocoded objects, you can do the following:

    obj.distance_to([43.9,-98.6])  # distance from obj to point
    obj.bearing_to([43.9,-98.6])   # bearing from obj to point
    obj.bearing_from(obj2)         # bearing from obj2 to obj

    The bearing_from/to methods take a single argument which can be: a [lat,lon] array, a geocoded object, or a geocodable address (string). The distance_from/to methods also take a units argument (:mi, :km, or :nm for nautical miles). See Distance and Bearing below for more info.

    One More Thing for MongoDB!

    Before you can call geocoded_by you'll need to include the necessary module using one of the following:

    include Geocoder::Model::Mongoid
    include Geocoder::Model::MongoMapper

    Latitude/Longitude Order in MongoDB

    Everywhere coordinates are passed to methods as two-element arrays, Geocoder expects them to be in the order: [lat, lon]. However, as per the GeoJSON spec, MongoDB requires that coordinates be stored longitude-first ([lon, lat]), so internally they are stored "backwards." Geocoder's methods attempt to hide this, so calling obj.to_coordinates (a method added to the object by Geocoder via geocoded_by) returns coordinates in the conventional order:

    obj.to_coordinates  # => [37.7941013, -122.3951096] # [lat, lon]

    whereas calling the object's coordinates attribute directly (obj.coordinates by default) returns the internal representation which is probably the reverse of what you want:

    obj.coordinates     # => [-122.3951096, 37.7941013] # [lon, lat]

    So, be careful.

    Use Outside of Rails

    To use Geocoder with ActiveRecord and a framework other than Rails (like Sinatra or Padrino), you will need to add this in your model before calling Geocoder methods:

    extend Geocoder::Model::ActiveRecord

    Geospatial Database Queries

    For ActiveRecord models:

    To find objects by location, use the following scopes:

    Venue.near('Omaha, NE, US')                   # venues within 20 miles of Omaha
    Venue.near([40.71, -100.23], 50)              # venues within 50 miles of a point
    Venue.near([40.71, -100.23], 50, units: :km)  # venues within 50 kilometres of a point
    Venue.geocoded                                # venues with coordinates
    Venue.not_geocoded                            # venues without coordinates

    With geocoded objects you can do things like this:

    if obj.geocoded?
      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
    end

    For MongoDB-backed models:

    Please do not use Geocoder's near method. Instead use MongoDB's built-in geospatial query language, which is faster. Mongoid also provides a DSL for geospatial queries.

    Geocoding HTTP Requests

    Geocoder adds location and safe_location methods 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

    The location method is vulnerable to trivial IP address spoofing via HTTP headers. If that's a problem for your application, use safe_location instead, but be aware that safe_location will not try to trace a request's originating IP through proxy headers; you will instead get the location of the last proxy the request passed through, if any (excepting any proxies you have explicitly whitelisted in your Rack config).

    Note that these methods will usually return nil in test and development environments because things like "localhost" and "0.0.0.0" are not geocodable IP addresses.

    Geocoding Service ("Lookup") Configuration

    Geocoder supports a variety of street and IP address geocoding services. The default lookups are :nominatim for street addresses and :ipinfo_io for IP addresses. Please see the API Guide for details on specific geocoding services (not all settings are supported by all services).

    To create a Rails initializer with sample configuration:

    rails generate geocoder:config

    Some common options are:

    # config/initializers/geocoder.rb
    Geocoder.configure(
    
      # street address geocoding service (default :nominatim)
      lookup: :yandex,
    
      # IP address geocoding service (default :ipinfo_io)
      ip_lookup: :maxmind,
    
      # to use an API key:
      api_key: "...",
    
      # geocoding service request timeout, in seconds (default 3):
      timeout: 5,
    
      # set default units to kilometers:
      units: :km,
    
      # caching (see [below](#caching) for details):
      cache: Redis.new,
      cache_prefix: "..."
    
    )

    Please see lib/geocoder/configuration.rb for a complete list of configuration options. Additionally, some lookups have their own special configuration options which are directly supported by Geocoder. For example, to specify a value for Google's bounds parameter: