From b572554ad8b3bcf8342d0c0a9d13b5e3cb247949 Mon Sep 17 00:00:00 2001
From: Alex Reisner <alex@alexreisner.com>
Date: Tue, 2 Oct 2012 00:25:04 -0400
Subject: [PATCH] Support versions 1.0 and 2.0 of Yahoo API.

Auto-detect which one is being used. It's necessary to continue
supporting 1.0 because of the existing data in people's caches.
See discussion: http://github.com/alexreisner/geocoder/pull/307
---
 lib/geocoder/lookups/yahoo.rb                 | 35 ++++++++++++--
 test/fixtures/yahoo_no_results.json           | 18 ++++----
 .../yahoo_v1_madison_square_garden.json       | 46 +++++++++++++++++++
 test/fixtures/yahoo_v1_no_results.json        | 10 ++++
 test/services_test.rb                         | 33 ++++++++++---
 test/test_helper.rb                           |  6 ++-
 6 files changed, 127 insertions(+), 21 deletions(-)
 create mode 100644 test/fixtures/yahoo_v1_madison_square_garden.json
 create mode 100644 test/fixtures/yahoo_v1_no_results.json

diff --git a/lib/geocoder/lookups/yahoo.rb b/lib/geocoder/lookups/yahoo.rb
index 2ab3a070..14004487 100644
--- a/lib/geocoder/lookups/yahoo.rb
+++ b/lib/geocoder/lookups/yahoo.rb
@@ -13,6 +13,38 @@ module Geocoder::Lookup
     def results(query)
       return [] unless doc = fetch_data(query)
       doc = doc['ResultSet']
+      if api_version(doc).to_i == 1
+        return version_1_results(doc)
+      elsif api_version(doc).to_i == 2
+        return version_2_results(doc)
+      else
+        warn "Yahoo Geocoding API error: #{doc['Error']} (#{doc['ErrorMessage']})."
+        return []
+      end
+    end
+
+    def api_version(doc)
+      if doc.include?('version')
+        return doc['version'].to_f
+      elsif doc.include?('@version')
+        return doc['@version'].to_f
+      end
+    end
+
+    def version_1_results(doc)
+      if doc['Error'] == 0
+        if doc['Found'] > 0
+          return doc['Results']
+        else
+          return []
+        end
+      end
+    end
+
+    ##
+    # Return array of results, or nil if an error.
+    #
+    def version_2_results(doc)
       # seems to have Error == 7 when no results, though this is not documented
       if [0, 7].include?(doc['Error'].to_i)
         if doc['Found'].to_i > 0
@@ -21,9 +53,6 @@ module Geocoder::Lookup
         else
           return []
         end
-      else
-        warn "Yahoo Geocoding API error: #{doc['Error']} (#{doc['ErrorMessage']})."
-        return []
       end
     end
 
diff --git a/test/fixtures/yahoo_no_results.json b/test/fixtures/yahoo_no_results.json
index b92d2b70..e97865df 100644
--- a/test/fixtures/yahoo_no_results.json
+++ b/test/fixtures/yahoo_no_results.json
@@ -1,12 +1,10 @@
 {
-    "@lang": "en-US",
-    "ResultSet": {
-        "@version": "2.0",
-        "@lang": "en-US",
-        "Error": "7",
-        "ErrorMessage": "No result",
-        "Locale": "en-US",
-        "Found": "0",
-        "Quality": "0"
-    }
+  "ResultSet":{
+    "version":"1.0",
+    "Error":0,
+    "ErrorMessage":"No error",
+    "Locale":"us_US",
+    "Quality":10,
+    "Found":0
+  }
 }
diff --git a/test/fixtures/yahoo_v1_madison_square_garden.json b/test/fixtures/yahoo_v1_madison_square_garden.json
new file mode 100644
index 00000000..6e54b8e7
--- /dev/null
+++ b/test/fixtures/yahoo_v1_madison_square_garden.json
@@ -0,0 +1,46 @@
+{
+  "ResultSet":{
+    "version":"1.0",
+    "Error":0,
+    "ErrorMessage":"No error",
+    "Locale":"us_US",
+    "Quality":90,
+    "Found":1,
+    "Results":[{
+      "quality":90,
+      "latitude":"40.750381",
+      "longitude":"-73.993988",
+      "offsetlat":"40.750381",
+      "offsetlon":"-73.993988",
+      "radius":100,
+      "name":"Madison Square Garden",
+      "line1":"Madison Square Garden",
+      "line2":"New York, NY  10001",
+      "line3":"",
+      "line4":"United States",
+      "house":"",
+      "street":"",
+      "xstreet":"",
+      "unittype":"",
+      "unit":"",
+      "postal":"10001",
+      "neighborhood":"",
+      "city":"New York",
+      "county":"New York County",
+      "state":"New York",
+      "country":"United States",
+      "countrycode":"US",
+      "statecode":"NY",
+      "countycode":"",
+      "uzip":"10001",
+      "hash":"",
+      "woeid":23617041,
+      "woetype":20,
+      "cross":"",
+      "timezone":"America/New_York",
+      "neighborhood":"Garment District|Midtown|Midtown West|Manhattan",
+      "areacode":"212",
+      "boundingbox":{"north":"40.750832","south":"40.749931","east":"-73.993393","west":"-73.994591"}
+    }]
+  }
+}
diff --git a/test/fixtures/yahoo_v1_no_results.json b/test/fixtures/yahoo_v1_no_results.json
new file mode 100644
index 00000000..e97865df
--- /dev/null
+++ b/test/fixtures/yahoo_v1_no_results.json
@@ -0,0 +1,10 @@
+{
+  "ResultSet":{
+    "version":"1.0",
+    "Error":0,
+    "ErrorMessage":"No error",
+    "Locale":"us_US",
+    "Quality":10,
+    "Found":0
+  }
+}
diff --git a/test/services_test.rb b/test/services_test.rb
index 6bda6b8f..0f44de51 100644
--- a/test/services_test.rb
+++ b/test/services_test.rb
@@ -67,17 +67,38 @@ class ServicesTest < Test::Unit::TestCase
 
   # --- Yahoo ---
 
-  def test_yahoo_result_components
+  def test_yahoo_v1_no_results
     Geocoder::Configuration.lookup = :yahoo
-    result = Geocoder.search("Madison Square Garden, New York, NY").first
+    assert_equal [], Geocoder.search("no results v1")
+  end
+
+  def test_yahoo_v1_result_components
+    Geocoder::Configuration.lookup = :yahoo
+    result = Geocoder.search("madison square garden v1").first
     assert_equal "10001", result.postal_code
   end
 
-  def test_yahoo_address_formatting
+  def test_yahoo_v1_address_formatting
     Geocoder::Configuration.lookup = :yahoo
-    result = Geocoder.search("Madison Square Garden, New York, NY").first
-    assert_equal "Madison Square Garden, New York, NY 10001, United States",
-      result.address
+    result = Geocoder.search("madison square garden v1").first
+    assert_equal "Madison Square Garden, New York, NY  10001, United States", result.address
+  end
+
+  def test_yahoo_v2_no_results
+    Geocoder::Configuration.lookup = :yahoo
+    assert_equal [], Geocoder.search("no results")
+  end
+
+  def test_yahoo_v2_result_components
+    Geocoder::Configuration.lookup = :yahoo
+    result = Geocoder.search("madison square garden v2").first
+    assert_equal "10001", result.postal_code
+  end
+
+  def test_yahoo_v2_address_formatting
+    Geocoder::Configuration.lookup = :yahoo
+    result = Geocoder.search("madison square garden v2").first
+    assert_equal "Madison Square Garden, New York, NY 10001, United States", result.address
   end
 
 
diff --git a/test/test_helper.rb b/test/test_helper.rb
index c77b44c1..b246afdd 100644
--- a/test/test_helper.rb
+++ b/test/test_helper.rb
@@ -93,8 +93,10 @@ module Geocoder
         raise TimeoutError if query.text == "timeout"
         raise SocketError if query.text == "socket_error"
         file = case query.text
-          when "no results";  :no_results
-          else                :madison_square_garden
+          when "no results v1"; :v1_no_results
+          when "madison square garden v1"; :v1_madison_square_garden
+          when "no results";    :no_results
+          else                  :madison_square_garden
         end
         read_fixture "yahoo_#{file}.json"
       end
-- 
GitLab