Skip to content

Commit

Permalink
Merge pull request geokit#1 from fragility/imajes_fix_yahoo
Browse files Browse the repository at this point in the history
Fix broken Yahoo! geocoder
  • Loading branch information
imajes committed Jan 20, 2012
2 parents c993b28 + b7ae467 commit c44143d
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 41 deletions.
82 changes: 56 additions & 26 deletions lib/geokit/geocoders.rb
Original file line number Diff line number Diff line change
Expand Up @@ -301,40 +301,70 @@ class YahooGeocoder < Geocoder
# Template method which does the geocode lookup.
def self.do_geocode(address, options = {})
address_str = address.is_a?(GeoLoc) ? address.to_geocodeable_s : address
url="http://api.local.yahoo.com/MapsService/V1/geocode?appid=#{Geokit::Geocoders::yahoo}&location=#{Geokit::Inflector::url_escape(address_str)}"
url="http://where.yahooapis.com/geocode?flags=J&appid=#{Geokit::Geocoders::yahoo}&q=#{Geokit::Inflector::url_escape(address_str)}"
res = self.call_geocoder_service(url)
return GeoLoc.new if !res.is_a?(Net::HTTPSuccess)
xml = res.body
doc = REXML::Document.new(xml)
logger.debug "Yahoo geocoding. Address: #{address}. Result: #{xml}"
json = res.body
logger.debug "Yahoo geocoding. Address: #{address}. Result: #{json}"
return self.json2GeoLoc(json, address)
end

if doc.elements['//ResultSet']
res=GeoLoc.new
def self.json2GeoLoc(json, address)
begin
results = ::ActiveSupport::JSON.decode(json)
rescue NameError => e
results = JSON.parse(json)
end

#basic
res.lat=doc.elements['//Latitude'].text
res.lng=doc.elements['//Longitude'].text
res.country_code=doc.elements['//Country'].text
res.provider='yahoo'

#extended - false if not available
res.city=doc.elements['//City'].text if doc.elements['//City'] && doc.elements['//City'].text != nil
res.state=doc.elements['//State'].text if doc.elements['//State'] && doc.elements['//State'].text != nil
res.zip=doc.elements['//Zip'].text if doc.elements['//Zip'] && doc.elements['//Zip'].text != nil
res.street_address=doc.elements['//Address'].text if doc.elements['//Address'] && doc.elements['//Address'].text != nil
res.precision=doc.elements['//Result'].attributes['precision'] if doc.elements['//Result']
# set the accuracy as google does (added by Andruby)
res.accuracy=%w{unknown country state state city zip zip+4 street address building}.index(res.precision)
res.success=true
return res
if results['ResultSet']['Error'] == 0
geoloc = nil
results['ResultSet']['Results'].each do |result|
extracted_geoloc = extract_geoloc(result)
if geoloc.nil?
geoloc = extracted_geoloc
else
geoloc.all.push(extracted_geoloc)
end
end
return geoloc
else
logger.info "Yahoo was unable to geocode address: "+address
logger.info "Yahoo was unable to geocode address: " + address
return GeoLoc.new
end
end

rescue
logger.info "Caught an error during Yahoo geocoding call: "+$!
return GeoLoc.new
def self.extract_geoloc(result_json)
geoloc = GeoLoc.new

# basic
geoloc.lat = result_json['latitude']
geoloc.lng = result_json['longitude']
geoloc.country_code = result_json['countrycode']
geoloc.provider = 'yahoo'

# extended
geoloc.street_address = result_json['line1'].to_s.empty? ? nil : result_json['line1']
geoloc.city = result_json['city']
geoloc.state = geoloc.is_us? ? result_json['statecode'] : result_json['state']
geoloc.zip = result_json['postal']

geoloc.precision = case result_json['quality']
when 9,10 then 'country'
when 19..30 then 'state'
when 39,40 then 'city'
when 49,50 then 'neighborhood'
when 59,60,64 then 'zip'
when 74,75 then 'zip+4'
when 70..72 then 'street'
when 80..87 then 'address'
when 62,63,90,99 then 'building'
else 'unknown'
end

geoloc.accuracy = %w{unknown country state state city zip zip+4 street address building}.index(geoloc.precision)
geoloc.success = true

return geoloc
end
end

Expand Down
26 changes: 11 additions & 15 deletions test/test_yahoo_geocoder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,11 @@

class YahooGeocoderTest < BaseGeocoderTest #:nodoc: all
YAHOO_FULL=<<-EOF.strip
<?xml version="1.0"?>
<ResultSet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:yahoo:maps" xsi:schemaLocation="urn:yahoo:maps http://api.local.yahoo.com/MapsService/V1/GeocodeResponse.xsd"><Result precision="address"><Latitude>37.792406</Latitude><Longitude>-122.39411</Longitude><Address>100 SPEAR ST</Address><City>SAN FRANCISCO</City><State>CA</State><Zip>94105-1522</Zip><Country>US</Country></Result></ResultSet>
<!-- ws01.search.scd.yahoo.com uncompressed/chunked Mon Jan 29 16:23:43 PST 2007 -->
{"ResultSet":{"version":"1.0","Error":0,"ErrorMessage":"No error","Locale":"us_US","Quality":87,"Found":1,"Results":[{"quality":87,"latitude":"37.792406","longitude":"-122.39411","offsetlat":"37.792332","offsetlon":"-122.394027","radius":500,"name":"","line1":"100 Spear St","line2":"San Francisco, CA 94105-1522","line3":"","line4":"United States","house":"100","street":"Spear St","xstreet":"","unittype":"","unit":"","postal":"94105-1522","neighborhood":"","city":"San Francisco","county":"San Francisco County","state":"California","country":"United States","countrycode":"US","statecode":"CA","countycode":"","uzip":"94105","hash":"0FA06819B5F53E75","woeid":12797156,"woetype":11}]}}
EOF

YAHOO_CITY=<<-EOF.strip
<?xml version="1.0"?>
<ResultSet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:yahoo:maps" xsi:schemaLocation="urn:yahoo:maps http://api.local.yahoo.com/MapsService/V1/GeocodeResponse.xsd"><Result precision="city"><Latitude>37.7742</Latitude><Longitude>-122.417068</Longitude><Address></Address><City>SAN FRANCISCO</City><State>CA</State><Zip></Zip><Country>US</Country></Result></ResultSet>
<!-- ws02.search.scd.yahoo.com uncompressed/chunked Mon Jan 29 18:00:28 PST 2007 -->
{"ResultSet":{"version":"1.0","Error":0,"ErrorMessage":"No error","Locale":"us_US","Quality":40,"Found":1,"Results":[{"quality":40,"latitude":"37.7742","longitude":"-122.417068","offsetlat":"37.7742","offsetlon":"-122.417068","radius":10700,"name":"","line1":"","line2":"San Francisco, CA","line3":"","line4":"United States","house":"","street":"","xstreet":"","unittype":"","unit":"","postal":"","neighborhood":"","city":"San Francisco","county":"San Francisco County","state":"California","country":"United States","countrycode":"US","statecode":"CA","countycode":"","uzip":"94102","hash":"","woeid":2487956,"woetype":7}]}}
EOF

def setup
Expand All @@ -27,40 +23,40 @@ def setup
def test_yahoo_full_address
response = MockSuccess.new
response.expects(:body).returns(YAHOO_FULL)
url = "http://api.local.yahoo.com/MapsService/V1/geocode?appid=Yahoo&location=#{Geokit::Inflector.url_escape(@address)}"
url = "http://where.yahooapis.com/geocode?flags=J&appid=Yahoo&q=#{Geokit::Inflector.url_escape(@full_address)}"
Geokit::Geocoders::YahooGeocoder.expects(:call_geocoder_service).with(url).returns(response)
do_full_address_assertions(Geokit::Geocoders::YahooGeocoder.geocode(@address))
do_full_address_assertions(Geokit::Geocoders::YahooGeocoder.geocode(@full_address))
end

def test_yahoo_full_address_accuracy
response = MockSuccess.new
response.expects(:body).returns(YAHOO_FULL)
url = "http://api.local.yahoo.com/MapsService/V1/geocode?appid=Yahoo&location=#{Geokit::Inflector.url_escape(@address)}"
url = "http://where.yahooapis.com/geocode?flags=J&appid=Yahoo&q=#{Geokit::Inflector.url_escape(@full_address)}"
Geokit::Geocoders::YahooGeocoder.expects(:call_geocoder_service).with(url).returns(response)
res = Geokit::Geocoders::YahooGeocoder.geocode(@address)
res = Geokit::Geocoders::YahooGeocoder.geocode(@full_address)
assert_equal 8, res.accuracy
end

def test_yahoo_full_address_with_geo_loc
response = MockSuccess.new
response.expects(:body).returns(YAHOO_FULL)
url = "http://api.local.yahoo.com/MapsService/V1/geocode?appid=Yahoo&location=#{Geokit::Inflector.url_escape(@full_address)}"
url = "http://where.yahooapis.com/geocode?flags=J&appid=Yahoo&q=#{Geokit::Inflector.url_escape(@full_address)}"
Geokit::Geocoders::YahooGeocoder.expects(:call_geocoder_service).with(url).returns(response)
do_full_address_assertions(Geokit::Geocoders::YahooGeocoder.geocode(@yahoo_full_loc))
end

def test_yahoo_city
response = MockSuccess.new
response.expects(:body).returns(YAHOO_CITY)
url = "http://api.local.yahoo.com/MapsService/V1/geocode?appid=Yahoo&location=#{Geokit::Inflector.url_escape(@address)}"
url = "http://where.yahooapis.com/geocode?flags=J&appid=Yahoo&q=#{Geokit::Inflector.url_escape(@address)}"
Geokit::Geocoders::YahooGeocoder.expects(:call_geocoder_service).with(url).returns(response)
do_city_assertions(Geokit::Geocoders::YahooGeocoder.geocode(@address))
end

def test_yahoo_city_accuracy
response = MockSuccess.new
response.expects(:body).returns(YAHOO_CITY)
url = "http://api.local.yahoo.com/MapsService/V1/geocode?appid=Yahoo&location=#{Geokit::Inflector.url_escape(@address)}"
url = "http://where.yahooapis.com/geocode?flags=J&appid=Yahoo&q=#{Geokit::Inflector.url_escape(@address)}"
Geokit::Geocoders::YahooGeocoder.expects(:call_geocoder_service).with(url).returns(response)
res = Geokit::Geocoders::YahooGeocoder.geocode(@address)
assert_equal 4, res.accuracy
Expand All @@ -69,14 +65,14 @@ def test_yahoo_city_accuracy
def test_yahoo_city_with_geo_loc
response = MockSuccess.new
response.expects(:body).returns(YAHOO_CITY)
url = "http://api.local.yahoo.com/MapsService/V1/geocode?appid=Yahoo&location=#{Geokit::Inflector.url_escape(@address)}"
url = "http://where.yahooapis.com/geocode?flags=J&appid=Yahoo&q=#{Geokit::Inflector.url_escape(@address)}"
Geokit::Geocoders::YahooGeocoder.expects(:call_geocoder_service).with(url).returns(response)
do_city_assertions(Geokit::Geocoders::YahooGeocoder.geocode(@yahoo_city_loc))
end

def test_service_unavailable
response = MockFailure.new
url = "http://api.local.yahoo.com/MapsService/V1/geocode?appid=Yahoo&location=#{Geokit::Inflector.url_escape(@address)}"
url = "http://where.yahooapis.com/geocode?flags=J&appid=Yahoo&q=#{Geokit::Inflector.url_escape(@address)}"
Geokit::Geocoders::YahooGeocoder.expects(:call_geocoder_service).with(url).returns(response)
assert !Geokit::Geocoders::YahooGeocoder.geocode(@yahoo_city_loc).success
end
Expand Down

0 comments on commit c44143d

Please sign in to comment.