Skip to content
Snippets Groups Projects
Commit a12fc5f3 authored by Dan Drinkard's avatar Dan Drinkard
Browse files

Add SmartyStreets lookup

parent 99623aba
No related branches found
No related tags found
No related merge requests found
......@@ -549,6 +549,17 @@ Data Science Toolkit provides an API whose reponse format is like Google's but w
* **Terms of Service**: http://geocod.io/terms-of-use
* **Limitations**: ?
#### SmartyStreets (`:smarty_streets`)
* **API key**: required
* **Quota**: 10,000 free, 250/month then purchase at sliding scale. Unlimited free for nonprofits & startups
* **Region**: US
* **SSL support**: yes
* **Languages**: en
* **Documentation**: http://smartystreets.com/kb/liveaddress-api/rest-endpoint
* **Terms of Service**: http://smartystreets.com/legal/terms-of-service
* **Limitations**: No reverse geocoding.
### IP Address Services
#### FreeGeoIP (`:freegeoip`)
......
......@@ -37,6 +37,7 @@ module Geocoder
:baidu,
:cloudmade,
:geocodio,
:smarty_streets,
:test
]
end
......
require 'geocoder/lookups/base'
require 'geocoder/results/smarty_streets'
module Geocoder::Lookup
class SmartyStreets < Base
def name
"SmartyStreets"
end
def required_api_key_parts
%w(auth-token)
end
def query_url(query)
return "#{protocol}://api.smartystreets.com/zipcode?#{url_query_string(query)}" if zipcode_only?(query)
"#{protocol}://api.smartystreets.com/street-address?#{url_query_string(query)}"
end
private # ---------------------------------------------------------------
def zipcode_only?(query)
return false if query.text.is_a?(Array)
return true unless (query.to_s.strip =~ /\A[\d]{5}(-[\d]{4})?\Z/).nil?
false
end
def query_url_params(query)
params = {}
if zipcode_only?(query)
params[:zipcode] = query.sanitized_text
else
params[:street] = query.sanitized_text
end
if configuration.api_key.is_a?(Array)
params[:"auth-id"] = configuration.api_key[0]
params[:"auth-token"] = configuration.api_key[1]
else
params[:"auth-token"] = configuration.api_key
end
params.merge(super)
end
def results(query)
return [] unless doc = fetch_data(query)
doc
end
end
end
#
# Results from the zipcode endpoint are completely different
# from the address endpoint. KeyError rescues below will
# return the appropriate value for each one.
# ---
require 'geocoder/lookups/base'
module Geocoder::Result
class SmartyStreets < Base
def coordinates
%w(latitude longitude).map{|i| (zipcode_result? && zipcodes.first[i]) ||
metadata[i] }
end
def address
begin
line_2 = delivery_line_2
rescue KeyError
line_2 = ''
end
"#{delivery_line_1} #{line_2} #{last_line}".strip.gsub(" ", " ") || nil
end
def state
components['state_abbreviation']
rescue KeyError
city_states.first['state']
end
def state_code
city_states.first['state_abbreviation']
rescue KeyError
state
end
def country
# SmartyStreets returns results for USA only
"US"
end
alias_method :country_code, :country
## Extra methods not in base.rb ------------------------
def street
components['street_name']
rescue KeyError
nil
end
def city
components['city_name']
rescue KeyError
city_states.first['city']
end
def zipcode
components['zipcode']
rescue KeyError
zipcodes.first['zipcode']
end
alias_method :postal_code, :zipcode
def zip4
components['plus4_code']
rescue KeyError
nil
end
alias_method :postal_code_extended, :zip4
def fips
metadata['county_fips']
rescue KeyError
zipcodes.first['county_fips']
end
def zipcode_result?
zipcodes.any? rescue false
end
# References to `components`, `metadata`, `city_states`, `zipcodes` land here.
def method_missing(meth, *args, &block)
@data.fetch(meth.to_s)
end
end
end
[
{
"input_index": 0,
"candidate_index": 0,
"addressee": "Madison Sq Garden",
"delivery_line_1": "2 Penn Plz Fl 15",
"last_line": "New York NY 10121-1703",
"delivery_point_barcode": "101211703022",
"components": {
"primary_number": "2",
"street_name": "Penn",
"street_suffix": "Plz",
"secondary_number": "15",
"secondary_designator": "Fl",
"city_name": "New York",
"state_abbreviation": "NY",
"zipcode": "10121",
"plus4_code": "1703",
"delivery_point": "02",
"delivery_point_check_digit": "2"
},
"metadata": {
"record_type": "F",
"zip_type": "Standard",
"county_fips": "36061",
"county_name": "New York",
"carrier_route": "C038",
"congressional_district": "12",
"rdi": "Commercial",
"elot_sequence": "0035",
"elot_sort": "A",
"latitude": 40.74959,
"longitude": -73.99251,
"precision": "Zip7",
"time_zone": "Eastern",
"utc_offset": -5.0,
"dst": true
},
"analysis": {
"dpv_match_code": "Y",
"dpv_footnotes": "AABB",
"dpv_cmra": "N",
"dpv_vacant": "N",
"active": "Y"
}
}
]
[]
\ No newline at end of file
# encoding: utf-8
require 'test_helper'
class SmartyStreetsTest < GeocoderTestCase
def setup
Geocoder.configure(lookup: :smarty_streets)
set_api_key!(:smarty_streets)
end
def test_url_contains_api_key
Geocoder.configure(:smarty_streets => {:api_key => 'blah'})
query = Geocoder::Query.new("Bluffton, SC")
assert_equal "http://api.smartystreets.com/street-address?auth-token=blah&street=Bluffton%2C+SC", query.url
end
def test_query_for_address_geocode
query = Geocoder::Query.new("42 Wallaby Way Sydney, AU")
assert_not_nil query.url =~ /api\.smartystreets\.com\/street-address\?/
end
def test_query_for_zipcode_geocode
query = Geocoder::Query.new("22204")
assert_not_nil query.url =~ /api\.smartystreets\.com\/zipcode\?/
end
def test_query_for_zipfour_geocode
query = Geocoder::Query.new("22204-1603")
assert_not_nil query.url =~ /api\.smartystreets\.com\/zipcode\?/
end
def test_smarty_streets_result_components
result = Geocoder.search("Madison Square Garden, New York, NY").first
assert_equal "Penn", result.street
assert_equal "10121", result.zipcode
assert_equal "1703", result.zip4
assert_equal "New York", result.city
assert_equal "36061", result.fips
end
def test_no_results
results = Geocoder.search("no results")
assert_equal 0, results.length
end
end
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment