From 53d5d112e8dbda4239067284323e2a04893b323d Mon Sep 17 00:00:00 2001 From: Evan Marks <marks.evan@gmail.com> Date: Sun, 6 Mar 2016 21:53:40 -0800 Subject: [PATCH] Add support for the LatLon.io geocoder service --- README.md | 11 ++++ lib/geocoder/lookup.rb | 3 +- lib/geocoder/lookups/latlon.rb | 59 ++++++++++++++++++++ lib/geocoder/results/latlon.rb | 71 ++++++++++++++++++++++++ test/fixtures/latlon_6000_universal_blvd | 16 ++++++ test/fixtures/latlon_invalid_key | 6 ++ test/fixtures/latlon_no_results | 6 ++ test/test_helper.rb | 8 +++ test/unit/lookups/latlon_test.rb | 42 ++++++++++++++ 9 files changed, 221 insertions(+), 1 deletion(-) create mode 100644 lib/geocoder/lookups/latlon.rb create mode 100644 lib/geocoder/results/latlon.rb create mode 100644 test/fixtures/latlon_6000_universal_blvd create mode 100644 test/fixtures/latlon_invalid_key create mode 100644 test/fixtures/latlon_no_results create mode 100644 test/unit/lookups/latlon_test.rb diff --git a/README.md b/README.md index 605c5bb6..a71dd671 100644 --- a/README.md +++ b/README.md @@ -663,6 +663,17 @@ This uses the PostcodeAnywhere UK Geocode service, this will geocode any string * **Limitations**: ? * **Notes**: To use PostcodeAnywhere you must include an API key: `Geocoder.configure(:lookup => :postcode_anywhere_uk, :api_key => 'your_api_key')`. +#### LatLon.io (`:latlon`) + +* **API key**: required +* **Quota**: Depends on the user's plan (free and paid plans available) +* **Region**: US +* **SSL support**: yes +* **Languages**: en +* **Documentation**: https://latlon.io/documentation +* **Terms of Service**: ? +* **Limitations**: No restrictions on use + ### IP Address Services diff --git a/lib/geocoder/lookup.rb b/lib/geocoder/lookup.rb index c4896085..92d5a50b 100644 --- a/lib/geocoder/lookup.rb +++ b/lib/geocoder/lookup.rb @@ -45,7 +45,8 @@ module Geocoder :okf, :postcode_anywhere_uk, :geoportail_lu, - :test + :test, + :latlon ] end diff --git a/lib/geocoder/lookups/latlon.rb b/lib/geocoder/lookups/latlon.rb new file mode 100644 index 00000000..0e1faee4 --- /dev/null +++ b/lib/geocoder/lookups/latlon.rb @@ -0,0 +1,59 @@ +require 'geocoder/lookups/base' +require 'geocoder/results/latlon' + +module Geocoder::Lookup + class Latlon < Base + + def name + "LatLon.io" + end + + def required_api_key_parts + ["api_key"] + end + + def query_url(query) + "#{protocol}://latlon.io/api/v1/#{if query.reverse_geocode? then 'reverse_' end}geocode?#{url_query_string(query)}" + end + + private # --------------------------------------------------------------- + + def results(query) + return [] unless doc = fetch_data(query) + if doc['error'].nil? + [doc] + # The API returned a 404 response, which indicates no results found + elsif doc['error']['type'] == 'api_error' + [] + elsif + doc['error']['type'] == 'authentication_error' + raise_error(Geocoder::InvalidApiKey) || + Geocoder.log(:warn, "LatLon.io service error: invalid API key.") + else + [] + end + end + + def supported_protocols + [:https] + end + + private # --------------------------------------------------------------- + + def query_url_params(query) + if query.reverse_geocode? + { + :token => configuration.api_key, + :lat => query.coordinates[0], + :lon => query.coordinates[1] + }.merge(super) + else + { + :token => configuration.api_key, + :address => query.sanitized_text + }.merge(super) + end + end + + end +end diff --git a/lib/geocoder/results/latlon.rb b/lib/geocoder/results/latlon.rb new file mode 100644 index 00000000..0f106bf2 --- /dev/null +++ b/lib/geocoder/results/latlon.rb @@ -0,0 +1,71 @@ +require 'geocoder/results/base' + +module Geocoder::Result + class Latlon < Base + + def city + address_components["city"] + end + + def coordinates + [@data['lat'].to_f, @data['lon'].to_f] + end + + def country + "United States" # LatLon.io only supports the US + end + + def country_code + "US" # LatLon.io only supports the US + end + + def formatted_address(format = :full) + address_components["address"] + end + alias_method :address, :formatted_address + + def number + address_components["number"] + end + + def prefix + address_components["prefix"] + end + + def state + address_components["state"] + end + alias_method :state_code, :state + + def street + [street_name, street_type].compact.join(' ') + end + + def street_name + address_components["street_name"] + end + + def street_type + address_components["street_type"] + end + + def suffix + address_components["suffix"] + end + + def unit + address_components["unit"] + end + + def zip + address_components["zip"] + end + alias_method :postal_code, :zip + + private + + def address_components + @data["address"] || {} + end + end +end diff --git a/test/fixtures/latlon_6000_universal_blvd b/test/fixtures/latlon_6000_universal_blvd new file mode 100644 index 00000000..97baa14f --- /dev/null +++ b/test/fixtures/latlon_6000_universal_blvd @@ -0,0 +1,16 @@ +{ + "lat": 28.4750507575094, + "lon": -81.4630386931719, + "address": { + "address": "6000 Universal Blvd, Orlando, FL 32819", + "prefix": null, + "number": "6000", + "street_name": "Universal", + "street_type": "Blvd", + "suffix": null, + "unit": null, + "city": "Orlando", + "state": "FL", + "zip": "32819" + } +} \ No newline at end of file diff --git a/test/fixtures/latlon_invalid_key b/test/fixtures/latlon_invalid_key new file mode 100644 index 00000000..d00ea46f --- /dev/null +++ b/test/fixtures/latlon_invalid_key @@ -0,0 +1,6 @@ +{ + "error": { + "type": "authentication_error", + "message": "Failed to authenticate your request." + } +} \ No newline at end of file diff --git a/test/fixtures/latlon_no_results b/test/fixtures/latlon_no_results new file mode 100644 index 00000000..f0d05791 --- /dev/null +++ b/test/fixtures/latlon_no_results @@ -0,0 +1,6 @@ +{ + "error": { + "type": "api_error", + "message": "The requested resource could not be found." + } +} diff --git a/test/test_helper.rb b/test/test_helper.rb index d6519f24..973bd083 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -312,6 +312,14 @@ module Geocoder "#{fixture_prefix}_boulevard_royal" end end + + require 'geocoder/lookups/latlon' + class Latlon + private + def default_fixture_filename + "latlon_6000_universal_blvd" + end + end end end diff --git a/test/unit/lookups/latlon_test.rb b/test/unit/lookups/latlon_test.rb new file mode 100644 index 00000000..2dcb47a9 --- /dev/null +++ b/test/unit/lookups/latlon_test.rb @@ -0,0 +1,42 @@ +# encoding: utf-8 +require 'test_helper' + +class LatlonTest < GeocoderTestCase + + def setup + Geocoder.configure(lookup: :latlon) + set_api_key!(:latlon) + end + + def test_result_components + result = Geocoder.search("6000 Universal Blvd, Orlando, FL 32819").first + assert_equal "6000", result.number + assert_equal "Universal", result.street_name + assert_equal "Blvd", result.street_type + assert_equal "Universal Blvd", result.street + assert_equal "Orlando", result.city + assert_equal "FL", result.state + assert_equal "32819", result.zip + assert_equal "6000 Universal Blvd, Orlando, FL 32819", result.formatted_address + assert_equal(28.4750507575094, result.latitude) + assert_equal(-81.4630386931719, result.longitude) + end + + def test_no_results + results = Geocoder.search("no results") + assert_equal 0, results.length + end + + def test_latlon_reverse_url + query = Geocoder::Query.new([45.423733, -75.676333]) + assert_match /reverse_geocode/, query.url + end + + def test_raises_api_key_exception + Geocoder.configure Geocoder.configure(:always_raise => [Geocoder::InvalidApiKey]) + assert_raises Geocoder::InvalidApiKey do + Geocoder.search("invalid key") + end + end + +end -- GitLab