Skip to content
Snippets Groups Projects
Commit 381c289f authored by Alex Reisner's avatar Alex Reisner
Browse files

Merge pull request #730 from rob-murray/add-postcode-anywhere-uk

Add :postcode_anywhere_uk lookup.
parents 8b52f445 4bb41db8
No related branches found
No related tags found
No related merge requests found
Showing
with 198 additions and 0 deletions
......@@ -607,6 +607,22 @@ Data Science Toolkit provides an API whose reponse format is like Google's but w
* **Terms of Service**: http://www.itella.fi/liitteet/palvelutjatuotteet/yhteystietopalvelut/Postinumeropalvelut-Palvelukuvausjakayttoehdot.pdf
* **Limitations**: ?
#### PostcodeAnywhere Uk (`:postcode_anywhere_uk`)
This uses the PostcodeAnywhere UK Geocode service, this will geocode any string from UK postcode, placename, point of interest or location.
* **API key**: required
* **Quota**: Dependant on service plan?
* **Region**: UK
* **SSL support**: yes
* **Languages**: English
* **Documentation**: [http://www.postcodeanywhere.co.uk/Support/WebService/Geocoding/UK/Geocode/2/](http://www.postcodeanywhere.co.uk/Support/WebService/Geocoding/UK/Geocode/2/)
* **Terms of Service**: ?
* **Limitations**: ?
* **Notes**: To use PostcodeAnywhere you must include an API key: `Geocoder.configure(:lookup => :postcode_anywhere_uk, :api_key => 'your_api_key')`.
### IP Address Services
#### FreeGeoIP (`:freegeoip`)
......
......@@ -40,6 +40,7 @@ module Geocoder
:geocodio,
:smarty_streets,
:okf,
:postcode_anywhere_uk,
:test
]
end
......
require 'geocoder/lookups/base'
require 'geocoder/results/postcode_anywhere_uk'
module Geocoder::Lookup
class PostcodeAnywhereUk < Base
# API documentation: http://www.postcodeanywhere.co.uk/Support/WebService/Geocoding/UK/Geocode/2/
BASE_URL_GEOCODE_V2_00 = 'services.postcodeanywhere.co.uk/Geocoding/UK/Geocode/v2.00/json.ws'
DAILY_LIMIT_EXEEDED_ERROR_CODES = ['8', '17'] # api docs say these two codes are the same error
INVALID_API_KEY_ERROR_CODE = '2'
def name
'PostcodeAnywhereUk'
end
def required_api_key_parts
%w(key)
end
def query_url(query)
format('%s://%s?%s', protocol, BASE_URL_GEOCODE_V2_00, url_query_string(query))
end
private
def results(query)
response = fetch_data(query)
return [] if response.nil? || !response.is_a?(Array) || response.empty?
raise_exception_for_response(response[0]) if response[0]['Error']
response
end
def raise_exception_for_response(response)
case response['Error']
when *DAILY_LIMIT_EXEEDED_ERROR_CODES
raise_error(Geocoder::OverQueryLimitError, response['Cause']) || warn(response['Cause'])
when INVALID_API_KEY_ERROR_CODE
raise_error(Geocoder::InvalidApiKey, response['Cause']) || warn(response['Cause'])
else # anything else just raise general error with the api cause
raise_error(Geocoder::Error, response['Cause']) || warn(response['Cause'])
end
end
def query_url_params(query)
{
:location => query.sanitized_text,
:key => configuration.api_key
}.merge(super)
end
end
end
require 'geocoder/results/base'
module Geocoder::Result
class PostcodeAnywhereUk < Base
def coordinates
[@data['Latitude'].to_f, @data['Longitude'].to_f]
end
def blank_result
''
end
alias_method :state, :blank_result
alias_method :state_code, :blank_result
alias_method :postal_code, :blank_result
def address
@data['Location']
end
def city
# is this too big a jump to assume that the API always
# returns a City, County as the last elements?
city = @data['Location'].split(',')[-2] || blank_result
city.strip
end
def os_grid
@data['OsGrid']
end
# This is a UK only API; all results are UK specific and
# so ommitted from API response.
def country
'United Kingdom'
end
def country_code
'UK'
end
end
end
[{"Location":"Moseley Road, Hallow, Worcester","Easting":"381676","Northing":"259425","Latitude":"52.2327","Longitude":"-2.2697","OsGrid":"SO 81676 59425","Accuracy":"Standard"}]
\ No newline at end of file
[{"Error":"9999","Description":"A generic error","Cause":"A generic error occured.","Resolution":"Fix the unknown error."}]
\ No newline at end of file
[{"Location":"Hampshire","Easting":"448701","Northing":"126642","Latitude":"51.037","Longitude":"-1.3068","OsGrid":"SU 48701 26642","Accuracy":"Standard"}]
\ No newline at end of file
[{"Error":"8","Description":"Key daily limit exceeded","Cause":"The daily limit on the key has been exceeded.","Resolution":"Alter the daily limit on the key. Check the usage details first to see if usage is normal."}]
\ No newline at end of file
[]
\ No newline at end of file
[{"Location":"Romsey, Hampshire","Easting":"435270","Northing":"121182","Latitude":"50.9889","Longitude":"-1.4989","OsGrid":"SU 35270 21182","Accuracy":"Standard"}]
\ No newline at end of file
[{"Error":"2","Description":"Unknown key","Cause":"The key you are using to access the service was not found.","Resolution":"Please check that the key is correct. It should be in the form AA11-AA11-AA11-AA11."}]
\ No newline at end of file
......@@ -214,6 +214,17 @@ module Geocoder
"okf_kirstinmaki"
end
end
class PostcodeAnywhereUk
private
def fixture_prefix
'postcode_anywhere_uk_geocode_v2_00'
end
def default_fixture_filename
"#{fixture_prefix}_romsey"
end
end
end
end
......
# encoding: utf-8
$: << File.join(File.dirname(__FILE__), '..', '..')
require 'test_helper'
class PostcodeAnywhereUkTest < GeocoderTestCase
def setup
Geocoder.configure(lookup: :postcode_anywhere_uk)
set_api_key!(:postcode_anywhere_uk)
end
def test_result_components_with_placename_search
results = Geocoder.search('Romsey')
assert_equal 1, results.size
assert_equal 'Romsey, Hampshire', results.first.address
assert_equal 'SU 35270 21182', results.first.os_grid
assert_equal [50.9889, -1.4989], results.first.coordinates
assert_equal 'Romsey', results.first.city
end
def test_result_components_with_postcode
results = Geocoder.search('WR26NJ')
assert_equal 1, results.size
assert_equal 'Moseley Road, Hallow, Worcester', results.first.address
assert_equal 'SO 81676 59425', results.first.os_grid
assert_equal [52.2327, -2.2697], results.first.coordinates
assert_equal 'Hallow', results.first.city
end
def test_result_components_with_county
results = Geocoder.search('hampshire')
assert_equal 1, results.size
assert_equal 'Hampshire', results.first.address
assert_equal 'SU 48701 26642', results.first.os_grid
assert_equal [51.037, -1.3068], results.first.coordinates
assert_equal '', results.first.city
end
def test_no_results
assert_equal [], Geocoder.search('no results')
end
def test_key_limit_exceeded_error
Geocoder.configure(always_raise: [Geocoder::OverQueryLimitError])
assert_raises Geocoder::OverQueryLimitError do
Geocoder.search('key limit exceeded')
end
end
def test_unknown_key_error
Geocoder.configure(always_raise: [Geocoder::InvalidApiKey])
assert_raises Geocoder::InvalidApiKey do
Geocoder.search('unknown key')
end
end
def test_generic_error
Geocoder.configure(always_raise: [Geocoder::Error])
exception = assert_raises(Geocoder::Error) do
Geocoder.search('generic error')
end
assert_equal 'A generic error occured.', exception.message
end
end
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment