README.md in geocoder-1.1.5 vs README.md in geocoder-1.1.6

- old
+ new

@@ -5,44 +5,38 @@ Compatibility ------------- -* Supports multiple Ruby versions: Ruby 1.8.7, 1.9.2, and JRuby. +* Supports multiple Ruby versions: Ruby 1.8.7, 1.9.2, 1.9.3, 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). +* Supports Rails 3.x. 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. -Install -------- +Installation +------------ -### As a Gem +Install Geocoder like any other Ruby gem: -Add to your Gemfile: + gem install geocoder +Or, if you're using Rails/Bundler, add this to your Gemfile: + gem "geocoder" and run at the command prompt: bundle install -### Or As a Plugin -At the command prompt: +Object Geocoding +---------------- - 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): +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 "Model 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`). @@ -79,10 +73,14 @@ include Geocoder::Model::Mongoid reverse_geocoded_by :coordinates after_validation :reverse_geocode # auto-fetch address +Once you've set up your model you'll need to create the necessary spatial indices in your database: + + rake db:mongoid:create_indexes + Be sure to read _Latitude/Longitude Order_ in the _Notes on MongoDB_ section below on how to properly retrieve latitude/longitude coordinates from your objects. ### MongoMapper MongoMapper is very similar to Mongoid, just be sure to include `Geocoder::Model::MongoMapper`. @@ -124,13 +122,15 @@ 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 + 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 Some utility methods are also available: # look up coordinates of some location (like searching Google Maps) Geocoder.coordinates("25 Main St, Cooperstown, NY") @@ -179,12 +179,12 @@ 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` or `:km`). -More on Configuration ---------------------- +Model Configuration +------------------- You are not stuck with using the `latitude` and `longitude` database column names (with ActiveRecord) or the `coordinates` array (Mongo) for storing coordinates. For example: geocoded_by :address, :latitude => :lat, :longitude => :lon # ActiveRecord geocoded_by :address, :coordinates => :coords # MongoDB @@ -255,36 +255,41 @@ Geocoding Services ------------------ -By default Geocoder uses Google's geocoding API to fetch coordinates and street addresses (FreeGeoIP is used for IP address info). However there are several other APIs supported, as well as a variety of settings. Please see the listing and comparison below for details on specific geocoding services (not all settings are supported by all services). Some common configuration options are: +By default Geocoder uses Google's geocoding API to fetch coordinates and street addresses (FreeGeoIP is the default for IP address info). However there are several other APIs supported, as well as a variety of settings. Please see the listing and comparison below for details on specific geocoding services (not all settings are supported by all services). Some common configuration options are: # config/initializers/geocoder.rb - Geocoder.configure do |config| + Geocoder.configure( # geocoding service (see below for supported options): - config.lookup = :yandex + :lookup => :yandex, # to use an API key: - config.api_key = "..." + :api_key => "...", # geocoding service request timeout, in seconds (default 3): - config.timeout = 5 + :timeout => 5, # set default units to kilometers: - config.units = :km + :units => :km, # caching (see below for details): - config.cache = Redis.new - config.cache_prefix = "..." + :cache => Redis.new, + :cache_prefix => "..." - end + ) -Please see lib/geocoder/configuration.rb for a complete list of configuration options. Additionally, some lookups have their own configuration options which are listed in the comparison chart below, and as of version 1.2.0 you can pass arbitrary parameters to any geocoding service. For example, to use Nominatim's `countrycodes` parameter: +Please see lib/geocoder/configuration.rb for a complete list of configuration options. Additionally, some lookups have their own configuration options, some of which are directly supported by Geocoder. For example, to specify a value for Google's `bounds` parameter: - Geocoder::Configuration.lookup = :nominatim + # with Google: + Geocoder.search("Paris", :bounds => [[32.1,-95.9], [33.9,-94.3]]) + +Please see the [source code for each lookup](https://github.com/alexreisner/geocoder/tree/master/lib/geocoder/lookups) to learn about directly supported parameters. Parameters which are not directly supported can be specified using the `:params` option, by which you can pass arbitrary parameters to any geocoding service. For example, to use Nominatim's `countrycodes` parameter: + + # with Nominatim: Geocoder.search("Paris", :params => {:countrycodes => "gb,de,fr,es,us"}) ### Listing and Comparison @@ -300,17 +305,17 @@ * **Languages**: ar, eu, bg, bn, ca, cs, da, de, el, en, en-AU, en-GB, es, eu, fa, fi, fil, fr, gl, gu, hi, hr, hu, id, it, iw, ja, kn, ko, lt, lv, ml, mr, nl, no, pl, pt, pt-BR, pt-PT, ro, ru, sk, sl, sr, sv, tl, ta, te, th, tr, uk, vi, zh-CN, zh-TW (see http://spreadsheets.google.com/pub?key=p9pdwsai2hDMsLkXsoM05KQ&gid=1) * **Extra options**: `:bounds` - pass SW and NE coordinates as an array of two arrays to bias results towards a viewport * **Documentation**: http://code.google.com/apis/maps/documentation/geocoding/#JSON * **Terms of Service**: http://code.google.com/apis/maps/terms.html#section_10_12 * **Limitations**: "You must not use or display the Content without a corresponding Google map, unless you are explicitly permitted to do so in the Maps APIs Documentation, or through written permission from Google." "You must not pre-fetch, cache, or store any Content, except that you may store: (i) limited amounts of Content for the purpose of improving the performance of your Maps API Implementation..." -* **Notes**: To use Google Premier set `Geocoder::Configuration.lookup = :google_premier` and `Geocoder::Configuration.api_key = [key, client, channel]`. +* **Notes**: To use Google Premier set `Geocoder.configure(:lookup => :google_premier, :api_key => [key, client, channel])`. #### Yahoo BOSS (`:yahoo`) Yahoo BOSS is **not a free service**. As of November 17, 2012 Yahoo no longer offers a free geocoding API. -* **API key**: requires OAuth consumer key and secret (set `Geocoder::Configuration.api_key = [key, secret]`) +* **API key**: requires OAuth consumer key and secret (set `Geocoder.configure(:api_key => [key, secret])`) * **Key signup**: http://developer.yahoo.com/boss/geo/ * **Quota**: unlimited, but subject to usage fees * **Region**: world * **SSL support**: no * **Languages**: en, fr, de, it, es, pt, nl, zh, ja, ko @@ -366,11 +371,11 @@ #### Mapquest (`:mapquest`) * **API key**: required for the licensed API, do not use for open tier * **Quota**: ? * **HTTP Headers**: in order to use the licensed API you can configure the http_headers to include a referer as so: - `Geocoder::Configuration.http_headers = { "Referer" => "http://foo.com" }` + `Geocoder.configure(:http_headers => { "Referer" => "http://foo.com" })` You can also allow a blank referer from the API management console via mapquest but it is potentially a security risk that someone else could use your API key from another domain. * **Region**: world * **SSL support**: no * **Languages**: English * **Documentation**: http://www.mapquestapi.com/geocoding/ @@ -386,17 +391,28 @@ * **Languages**: English * **Documentation**: http://github.com/fiorix/freegeoip/blob/master/README.rst * **Terms of Service**: ? * **Limitations**: ? +#### MaxMind Web Services (`:maxmind`) +* **API key**: required +* **Quota**: Request Packs can be purchased +* **Region**: world +* **SSL support**: yes +* **Languages**: English +* **Documentation**: http://www.maxmind.com/app/web_services +* **Terms of Service**: ? +* **Limitations**: ? + + Caching ------- It's a good idea, when relying on any external service, to cache retrieved data. When implemented correctly it improves your app's response time and stability. It's easy to cache geocoding results with Geocoder, just configure a cache store: - Geocoder::Configuration.cache = Redis.new + Geocoder.configure(:cache => Redis.new) This example uses Redis, but the cache store can be any object that supports these methods: * `store#[](key)` - retrieves a value * `store#[]=(key, value)` - stores a value @@ -405,11 +421,11 @@ Even a plain Ruby hash will work, though it's not a great choice (cleared out when app is restarted, not shared between app instances, etc). You can also set a custom prefix to be used for cache keys: - Geocoder::Configuration.cache_prefix = "..." + Geocoder.configure(:cache_prefix => "...") By default the prefix is `geocoder:` If you need to expire cached content: @@ -461,19 +477,19 @@ You can use Geocoder outside of Rails by calling the `Geocoder.search` method: results = Geocoder.search("McCarren Park, Brooklyn, NY") -This returns an array of `Geocoder::Result` objects with all information provided by the geocoding service. Please see above and in the code for details. +This returns an array of `Geocoder::Result` objects with all data provided by the geocoding service. Testing Apps that Use Geocoder ------------------------------ When writing tests for an app that uses Geocoder it may be useful to avoid network calls and have Geocoder return consistent, configurable results. To do this, configure and use the `:test` lookup. For example: - Geocoder::Configuration.lookup = :test + Geocoder.configure(:lookup => :test) Geocoder::Lookup::Test.add_stub( "New York, NY", [ { 'latitude' => 40.7143528, @@ -505,11 +521,10 @@ Country: United States Google map: http://maps.google.com/maps?q=29.952211,-90.080563 There are also a number of options for setting the geocoding API, key, and language, viewing the raw JSON reponse, and more. Please run `geocode -h` for details. - Notes on MongoDB ---------------- ### The Near Method @@ -527,10 +542,17 @@ obj.coordinates # => [-122.3951096, 37.7941013] # [lon, lat] For consistency with the rest of Geocoder, always use the `to_coordinates` method instead. +Notes on Non-Rails Frameworks +----------------------------- + +If you are using 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 + Optimisation of Distance Queries -------------------------------- In MySQL and Postgres the finding of objects near a given point is speeded up by using a bounding box to limit the number of points over which a full distance calculation needs to be done. @@ -567,18 +589,47 @@ Error Handling -------------- -By default Geocoder will rescue any exceptions raised by calls to the geocoding service and return an empty array (using warn() to inform you of the error). You can override this and implement custom error handling for certain exceptions by using the `:always_raise` option: +By default Geocoder will rescue any exceptions raised by calls to a geocoding service and return an empty array (using warn() to inform you of the error). You can override this on a per-exception basis, and also have Geocoder raise its own exceptions for certain events (eg: API quota exceeded) by using the `:always_raise` option: - Geocoder::Configuration.always_raise = [SocketError, TimeoutError] + Geocoder.configure(:always_raise => [SocketError, TimeoutError]) You can also do this to raise all exceptions: - Geocoder::Configuration.always_raise = :all + Geocoder.configure(:always_raise => :all) -See `lib/geocoder/exceptions.rb` for a list of raise-able exceptions. +The raise-able exceptions are: + + SocketError + TimeoutError + Geocoder::OverQueryLimitError + Geocoder::RequestDenied + Geocoder::InvalidRequest + Geocoder::InvalidApiKey + +Note that not all lookups support all exceptions. + + +Troubleshooting +--------------- + +### Mongoid + +If you get one of these errors: + + uninitialized constant Geocoder::Model::Mongoid + uninitialized constant Geocoder::Model::Mongoid::Mongo + +you should check your Gemfile to make sure the Mongoid gem is listed _before_ Geocoder. If Mongoid isn't loaded when Geocoder is initialized, Geocoder will not load support for Mongoid. + +### ActiveRecord + +A lot of debugging time can be saved by understanding how Geocoder works with ActiveRecord. When you use the `near` scope or the `nearbys` method of a geocoded object, Geocoder creates an ActiveModel::Relation object which adds some attributes (eg: distance, bearing) to the SELECT clause. It also adds a condition to the WHERE clause to check that distance is within the given radius. Because the SELECT clause is modified, anything else that modifies the SELECT clause may produce strange results, for example: + +* using the `pluck` method (selects only a single column) +* specifying another model through `includes` (selects columns from other tables) Known Issue -----------