diff --git a/CHANGELOG.md b/CHANGELOG.md index fb8f6ee7ef4c91a6e55eaed6f695fd07a7b32dac..d58330bc8bbd87b8eb1daaac8e28a2a23445fb79 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ Major changes to Geocoder for each release. Please see the Git log for complete * Add :baidu_ip lookup (thanks github.com/yonggu). * Add :min_radius option to `near` scope (thanks github.com/phallstrom). * Fix: Yandex city attribute caused exception with certain responses (thanks github.com/dblock). +* Add support for Geocod.io API (thanks github.com/dblock). 1.1.9 (2013 Dec 11) ------------------- diff --git a/README.md b/README.md index 3521b2400354a11782ec31849a15802f0c26f5c1..1bca09f329e06c5e7e368f8c58e7bc8799c551bb 100644 --- a/README.md +++ b/README.md @@ -256,7 +256,7 @@ When querying for objects (if you're using ActiveRecord) you can also look withi This can also dramatically improve query performance, especially when used in conjunction with indexes on the latitude/longitude columns. Note, however, that returned results do not include `distance` and `bearing` attributes. Note that `#near` performs both bounding box and radius queries for speed. -You can also specify a minimum radius (if you're using ActiveRecord and not Sqlite) to constrain the +You can also specify a minimum radius (if you're using ActiveRecord and not Sqlite) to constrain the lower bound (ie. think of a donut, or ring) by using the `:min_radius` option: box = Geocoder::Calculations.bounding_box(center_point, distance, :min_radius => 10.5) @@ -522,6 +522,17 @@ Data Science Toolkit provides an API whose reponse format is like Google's but w * **Terms of Service**: http://cloudmade.com/api-terms-of-service * **Limitations**: ? +#### Geocodio (`:geocodio`) + +* **API key**: required +* **Quota**: 2,500 free requests/day then purchase $.001 for each +* **Region**: US +* **SSL support**: no +* **Languages**: en +* **Documentation**: http://geocod.io/docs +* **Terms of Service**: http://geocod.io/terms-of-use +* **Limitations**: ? + ### IP Address Services #### FreeGeoIP (`:freegeoip`) @@ -558,7 +569,7 @@ Data Science Toolkit provides an API whose reponse format is like Google's but w * **Terms of Service**: ? * **Limitations**: ? * **Notes**: You must add the **geoip** gem to your Gemfile or have it installed in your system. You also have to specify the path of the MaxMind database in your configuration. For example: - + `Geocoder.configure(:ip_lookup => :maxmind_local, :maxmind_local => {:database => File.join('folder', 'GeoLiteCity.dat')})` #### Baidu IP (`:baidu_ip`) diff --git a/lib/geocoder/lookup.rb b/lib/geocoder/lookup.rb index 104de94ce816189cac2bb113013aeeefa9d1b944..fbfec2f8d364e557841e7cab7636256f54d7cea4 100644 --- a/lib/geocoder/lookup.rb +++ b/lib/geocoder/lookup.rb @@ -35,6 +35,7 @@ module Geocoder :ovi, :baidu, :cloudmade, + :geocodio, :test ] end diff --git a/lib/geocoder/lookups/geocodio.rb b/lib/geocoder/lookups/geocodio.rb new file mode 100644 index 0000000000000000000000000000000000000000..d3fc8f97d761fd3e6b6320b203277b2c1222469c --- /dev/null +++ b/lib/geocoder/lookups/geocodio.rb @@ -0,0 +1,34 @@ +require 'geocoder/lookups/base' +require "geocoder/results/geocodio" + +module Geocoder::Lookup + class Geocodio < Base + + def name + "Geocodio" + end + + def query_url(query) + "#{protocol}://api.geocod.io/v1/geocode?#{url_query_string(query)}" + end + + def results(query) + return [] unless doc = fetch_data(query) + if doc['error'].nil? + return doc["results"] + else + warn "Geocodio service error: #{doc['error']}." + end + [] + end + + private # --------------------------------------------------------------- + + def query_url_params(query) + { + :api_key => configuration.api_key, + :q => query.sanitized_text + }.merge(super) + end + end +end diff --git a/lib/geocoder/results/geocodio.rb b/lib/geocoder/results/geocodio.rb new file mode 100644 index 0000000000000000000000000000000000000000..e80c750f58c7d148a0a9a35d23f4e29ba5d5aa72 --- /dev/null +++ b/lib/geocoder/results/geocodio.rb @@ -0,0 +1,66 @@ +require 'geocoder/results/base' + +module Geocoder::Result + class Geocodio < Base + def number + address_components["number"] + end + + def street + address_components["street"] + end + + def suffix + address_components["suffix"] + end + + def state + address_components["state"] + end + alias_method :state_code, :state + + def zip + address_components["zip"] + end + alias_method :postal_code, :zip + + def country + "United States" # Geocodio only supports the US + end + + def country_code + "US" # Geocodio only supports the US + end + + def city + address_components["city"] + end + + def postdirectional + address_components["postdirectional"] + end + + def location + @data['location'] + end + + def coordinates + ['lat', 'lng'].map{ |i| location[i] } if location + end + + def accuracy + @data['accuracy'].to_f if @data.key?('accuracy') + end + + def formatted_address(format = :full) + @data['formatted_address'] + end + alias_method :address, :formatted_address + + private + + def address_components + @data['address_components'] || {} + end + end +end diff --git a/test/fixtures/geocodio_1101_pennsylvania_ave b/test/fixtures/geocodio_1101_pennsylvania_ave new file mode 100644 index 0000000000000000000000000000000000000000..c89bf170083818f5e30b7f07eb9bccbf8d6e7ff4 --- /dev/null +++ b/test/fixtures/geocodio_1101_pennsylvania_ave @@ -0,0 +1 @@ +{"input":{"address_components":{"number":"1101","street":"Pennsylvania","suffix":"Ave","postdirectional":"NW","city":"Washington","state":"DC"},"formatted_address":"1101 Pennsylvania Ave NW, Washington DC"},"results":[{"address_components":{"number":"1101","street":"Pennsylvania","suffix":"Ave","postdirectional":"NW","city":"Washington","state":"DC","zip":"20004"},"formatted_address":"1101 Pennsylvania Ave NW, Washington DC, 20004","location":{"lat":38.895019,"lng":-77.028095},"accuracy":1},{"address_components":{"number":"1101","street":"Pennsylvania","suffix":"Ave","postdirectional":"NW","city":"Washington","state":"DC","zip":"20004"},"formatted_address":"1101 Pennsylvania Ave NW, Washington DC, 20004","location":{"lat":38.895016122449,"lng":-77.028084377551},"accuracy":0.8}]} \ No newline at end of file diff --git a/test/fixtures/geocodio_no_results b/test/fixtures/geocodio_no_results new file mode 100644 index 0000000000000000000000000000000000000000..45b14b1aa7de9fe80c73d03536de88eb356f3367 --- /dev/null +++ b/test/fixtures/geocodio_no_results @@ -0,0 +1 @@ +{"input":{"address_components":{"number":"1101","street":"Pennsylvania","suffix":"Ave","postdirectional":"NW","city":"Washington","state":"DC"},"formatted_address":"1101 Pennsylvania Ave NW, Washington DC"},"results":[]} diff --git a/test/services_test.rb b/test/services_test.rb index ad7f361bdeb570d8b2e446151377ba974bfb5815..f7c7ca61ac38fd812e8e5f6bc46ca4cfd41b3090 100644 --- a/test/services_test.rb +++ b/test/services_test.rb @@ -397,4 +397,27 @@ class ServicesTest < Test::Unit::TestCase assert_equal 2.2956200048981574, result.coordinates[1] end + # --- Geocodio --- + + def test_geocodio_result_components + Geocoder.configure(:lookup => :geocodio) + set_api_key!(:geocodio) + result = Geocoder.search("1101 Pennsylvania Ave NW, Washington DC").first + assert_equal 1.0, result.accuracy + assert_equal "1101", result.number + assert_equal "Ave", result.suffix + assert_equal "DC", result.state + assert_equal "20004", result.zip + assert_equal "NW", result.postdirectional + assert_equal "Washington", result.city + assert_equal "1101 Pennsylvania Ave NW, Washington DC, 20004", result.formatted_address + assert_equal({ "lat" => 38.895019, "lng" => -77.028095 }, result.location) + end + + def test_geocodio_no_results + Geocoder.configure(:lookup => :geocodio) + set_api_key!(:geocodio) + results = Geocoder.search("no results") + assert_equal 0, results.length + end end diff --git a/test/test_helper.rb b/test/test_helper.rb index 0035c55abdaeffdc9fa4e317af00a1e5e8af276c..20d3a13d568f81ffc5b5d49c072a6b72dead0418 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -174,6 +174,12 @@ module Geocoder end end + class Geocodio + private + def default_fixture_filename + "geocodio_1101_pennsylvania_ave" + end + end end end