Skip to content

Commit

Permalink
Add Melissa Data to API Options (#1521)
Browse files Browse the repository at this point in the history
Add :melissa_street lookup.
  • Loading branch information
ALacker authored Sep 1, 2021
1 parent f005838 commit 50a0e6b
Show file tree
Hide file tree
Showing 11 changed files with 308 additions and 3 deletions.
11 changes: 11 additions & 0 deletions README_API_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,17 @@ The [Google Places Search API](https://developers.google.com/maps/documentation/
* **Limitations**: ?
* **Notes**: You can use the open (non-licensed) API by setting: `Geocoder.configure(mapquest: {open: true})` (defaults to licensed version)
### Melissa Data (`:melissa_street`)
* **API key**: required
* **Key signup**: https://www.melissa.com/developer/
* **Quota**: ?
* **Region**: world
* **Languages**: English
* **Documentation**: https://www.melissa.com/developer/
* **Terms of Service**: https://www.melissa.com/terms
* **Limitations**: ?
### Nominatim (`:nominatim`)
* **API key**: none
Expand Down
1 change: 1 addition & 0 deletions lib/geocoder/lookup.rb
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ def street_services
:latlon,
:amap,
:osmnames,
:melissa_street,
:amazon_location_service,
:geoapify,
:photon
Expand Down
41 changes: 41 additions & 0 deletions lib/geocoder/lookups/melissa_street.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
require 'geocoder/lookups/base'
require "geocoder/results/melissa_street"

module Geocoder::Lookup
class MelissaStreet < Base

def name
"MelissaStreet"
end

def results(query)
return [] unless doc = fetch_data(query)

if doc["TransmissionResults"] == "GE05"
raise_error(Geocoder::InvalidApiKey) ||
Geocoder.log(:warn, "Melissa service error: invalid API key.")
end

return doc["Records"]
end

private # ---------------------------------------------------------------

def base_query_url(query)
"#{protocol}://address.melissadata.net/v3/WEB/GlobalAddress/doGlobalAddress?"
end

def query_url_params(query)
params = {
id: configuration.api_key,
format: "JSON",
a1: query.sanitized_text,
loc: query.options[:city],
admarea: query.options[:state],
postal: query.options[:postal],
ctry: query.options[:country]
}
params.merge(super)
end
end
end
46 changes: 46 additions & 0 deletions lib/geocoder/results/melissa_street.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
require 'geocoder/results/base'

module Geocoder::Result
class MelissaStreet < Base
def address(format = :full)
@data['FormattedAddress']
end

def street_address
@data['AddressLine1']
end

def suffix
@data['ThoroughfareTrailingType']
end

def number
@data['PremisesNumber']
end

def city
@data['Locality']
end

def state_code
@data['AdministrativeArea']
end
alias_method :state, :state_code

def country
@data['CountryName']
end

def country_code
@data['CountryISO3166_1_Alpha2']
end

def postal_code
@data['PostalCode']
end

def coordinates
[@data['Latitude'].to_f, @data['Longitude'].to_f]
end
end
end
6 changes: 6 additions & 0 deletions test/fixtures/melissa_street_invalid_key
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"Version": "3.0.1.167",
"TransmissionReference": "",
"TransmissionResults": "GE05",
"TotalRecords": "0"
}
73 changes: 73 additions & 0 deletions test/fixtures/melissa_street_low_accuracy
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
{
"Version": "3.0.1.167",
"TransmissionReference": "",
"TransmissionResults": "",
"TotalRecords": "1",
"Records": [
{
"RecordID": "1",
"Results": "AC16,AE11,AV13,GS03",
"FormattedAddress": "Frank H Ogawa Plaza;Oakland, CA 94612",
"Organization": "",
"AddressLine1": "Frank H Ogawa Plaza",
"AddressLine2": "Oakland, CA 94612",
"AddressLine3": "",
"AddressLine4": "",
"AddressLine5": "",
"AddressLine6": "",
"AddressLine7": "",
"AddressLine8": "",
"SubPremises": "",
"DoubleDependentLocality": "",
"DependentLocality": "",
"Locality": "Oakland",
"SubAdministrativeArea": "Alameda",
"AdministrativeArea": "CA",
"PostalCode": "94612",
"PostalCodeType": " ",
"AddressType": " ",
"AddressKey": "94612000000",
"SubNationalArea": "",
"CountryName": "United States of America",
"CountryISO3166_1_Alpha2": "US",
"CountryISO3166_1_Alpha3": "USA",
"CountryISO3166_1_Numeric": "840",
"CountrySubdivisionCode": "US-CA",
"Thoroughfare": "Frank H Ogawa Plz",
"ThoroughfarePreDirection": "",
"ThoroughfareLeadingType": "",
"ThoroughfareName": "Frank H Ogawa",
"ThoroughfareTrailingType": "Plz",
"ThoroughfarePostDirection": "",
"DependentThoroughfare": "",
"DependentThoroughfarePreDirection": "",
"DependentThoroughfareLeadingType": "",
"DependentThoroughfareName": "",
"DependentThoroughfareTrailingType": "",
"DependentThoroughfarePostDirection": "",
"Building": "",
"PremisesType": "",
"PremisesNumber": "",
"SubPremisesType": "",
"SubPremisesNumber": "",
"PostBox": "",
"Latitude": "37.806200",
"Longitude": "-122.268900",
"DeliveryIndicator": "U",
"MelissaAddressKey": "",
"MelissaAddressKeyBase": "",
"PostOfficeLocation": "",
"SubPremiseLevel": "",
"SubPremiseLevelType": "",
"SubPremiseLevelNumber": "",
"SubBuilding": "",
"SubBuildingType": "",
"SubBuildingNumber": "",
"UTC": "UTC-08:00",
"DST": "Y",
"DeliveryPointSuffix": "",
"CensusKey": "060014029001027",
"Extras": {}
}
]
}
73 changes: 73 additions & 0 deletions test/fixtures/melissa_street_oakland_city_hall
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
{
"Version": "3.0.1.167",
"TransmissionReference": "",
"TransmissionResults": "",
"TotalRecords": "1",
"Records": [
{
"RecordID": "1",
"Results": "AC10,AC14,AC16,AV14,GS05",
"FormattedAddress": "1 Frank H Ogawa Plz Fl 3;Oakland, CA 94612-1932",
"Organization": "",
"AddressLine1": "1 Frank H Ogawa Plz Fl 3",
"AddressLine2": "Oakland, CA 94612-1932",
"AddressLine3": "",
"AddressLine4": "",
"AddressLine5": "",
"AddressLine6": "",
"AddressLine7": "",
"AddressLine8": "",
"SubPremises": "Fl 3",
"DoubleDependentLocality": "",
"DependentLocality": "",
"Locality": "Oakland",
"SubAdministrativeArea": "Alameda",
"AdministrativeArea": "CA",
"PostalCode": "94612-1932",
"PostalCodeType": " ",
"AddressType": "H",
"AddressKey": "94612193299",
"SubNationalArea": "",
"CountryName": "United States of America",
"CountryISO3166_1_Alpha2": "US",
"CountryISO3166_1_Alpha3": "USA",
"CountryISO3166_1_Numeric": "840",
"CountrySubdivisionCode": "US-CA",
"Thoroughfare": "Frank H Ogawa Plz",
"ThoroughfarePreDirection": "",
"ThoroughfareLeadingType": "",
"ThoroughfareName": "Frank H Ogawa",
"ThoroughfareTrailingType": "Plz",
"ThoroughfarePostDirection": "",
"DependentThoroughfare": "",
"DependentThoroughfarePreDirection": "",
"DependentThoroughfareLeadingType": "",
"DependentThoroughfareName": "",
"DependentThoroughfareTrailingType": "",
"DependentThoroughfarePostDirection": "",
"Building": "",
"PremisesType": "",
"PremisesNumber": "1",
"SubPremisesType": "Fl",
"SubPremisesNumber": "3",
"PostBox": "",
"Latitude": "37.805402",
"Longitude": "-122.272797",
"DeliveryIndicator": "B",
"MelissaAddressKey": "9772863955",
"MelissaAddressKeyBase": "",
"PostOfficeLocation": "",
"SubPremiseLevel": "",
"SubPremiseLevelType": "",
"SubPremiseLevelNumber": "",
"SubBuilding": "",
"SubBuildingType": "",
"SubBuildingNumber": "",
"UTC": "UTC-08:00",
"DST": "Y",
"DeliveryPointSuffix": "",
"CensusKey": "060014028002040",
"Extras": {}
}
]
}
8 changes: 8 additions & 0 deletions test/test_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,14 @@ def default_fixture_filename
end
end

require 'geocoder/lookups/melissa_street'
class MelissaStreet
private
def default_fixture_filename
"melissa_street_oakland_city_hall"
end
end

require 'geocoder/lookups/postcode_anywhere_uk'
class PostcodeAnywhereUk
private
Expand Down
9 changes: 8 additions & 1 deletion test/unit/lookup_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,14 @@ def test_responds_to_name_method

def test_search_returns_empty_array_when_no_results
Geocoder::Lookup.all_services_except_test.each do |l|
next if [:abstract_api, :ipgeolocation, :ipqualityscore, :nationaal_georegister_nl].include?(l) # lookups that always return a result
next if [
:abstract_api,
:ipgeolocation,
:ipqualityscore,
:melissa_street,
:nationaal_georegister_nl
].include?(l) # lookups that always return a result

lookup = Geocoder::Lookup.get(l)
set_api_key!(l)
silence_warnings do
Expand Down
35 changes: 35 additions & 0 deletions test/unit/lookups/melissa_street_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# encoding: utf-8
require 'test_helper'

class MelissaStreetTest < GeocoderTestCase

def setup
Geocoder.configure(lookup: :melissa_street)
set_api_key!(:melissa_street)
end

def test_result_components
result = Geocoder.search("1 Frank H Ogawa Plz Fl 3").first
assert_equal "1", result.number
assert_equal "1 Frank H Ogawa Plz Fl 3", result.street_address
assert_equal "Plz", result.suffix
assert_equal "CA", result.state
assert_equal "94612-1932", result.postal_code
assert_equal "Oakland", result.city
assert_equal "US", result.country_code
assert_equal "United States of America", result.country
assert_equal([37.805402, -122.272797], result.coordinates)
end

def test_low_accuracy
result = Geocoder.search("low accuracy").first
assert_equal "United States of America", result.country
end

def test_raises_api_key_exception
Geocoder.configure(:always_raise => [Geocoder::InvalidApiKey])
assert_raises Geocoder::InvalidApiKey do
Geocoder.search("invalid key")
end
end
end
8 changes: 6 additions & 2 deletions test/unit/result_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,12 @@ def test_forward_geocoding_result_has_required_attributes

def test_reverse_geocoding_result_has_required_attributes
Geocoder::Lookup.all_services_except_test.each do |l|
next if l == :ip2location # has pay-per-attribute pricing model
next if l == :nationaal_georegister_nl # no reverse geocoding
next if [
:ip2location, # has pay-per-attribute pricing model
:nationaal_georegister_nl, # no reverse geocoding
:melissa_street, # reverse geocoding not implemented
].include?(l)

Geocoder.configure(:lookup => l)
set_api_key!(l)
result = Geocoder.search([45.423733, -75.676333]).first
Expand Down

0 comments on commit 50a0e6b

Please sign in to comment.