From 02bdc9e7ace4b3c8917cec08b9ceecd86a4c95f7 Mon Sep 17 00:00:00 2001
From: Alex Reisner <alex@alexreisner.com>
Date: Tue, 1 Mar 2011 23:57:37 -0500
Subject: [PATCH] Add support for Yahoo geocoding.

---
 lib/geocoder/lookups/yahoo.rb                 | 33 +++++++++++++++
 lib/geocoder/results/yahoo.rb                 | 28 +++++++++++++
 ...json => google_madison_square_garden.json} |  0
 .../fixtures/yahoo_madison_square_garden.json | 41 +++++++++++++++++++
 test/geocoder_test.rb                         | 21 ++++++++++
 test/test_helper.rb                           | 10 ++---
 6 files changed, 128 insertions(+), 5 deletions(-)
 create mode 100644 lib/geocoder/lookups/yahoo.rb
 create mode 100644 lib/geocoder/results/yahoo.rb
 rename test/fixtures/{madison_square_garden.json => google_madison_square_garden.json} (100%)
 create mode 100644 test/fixtures/yahoo_madison_square_garden.json

diff --git a/lib/geocoder/lookups/yahoo.rb b/lib/geocoder/lookups/yahoo.rb
new file mode 100644
index 00000000..10fc2b05
--- /dev/null
+++ b/lib/geocoder/lookups/yahoo.rb
@@ -0,0 +1,33 @@
+require 'geocoder/lookups/base'
+require "geocoder/results/yahoo"
+
+module Geocoder::Lookup
+  class Yahoo < Base
+
+    private # ---------------------------------------------------------------
+
+    ##
+    # Returns a parsed Yahoo geocoder search result (hash).
+    # Returns nil if non-200 HTTP response, timeout, or other error.
+    #
+    def results(query, reverse = false)
+      doc = fetch_data(query, reverse)
+      if doc = doc['ResultSet'] and doc['Error'] == 0
+        doc['Results']
+      else
+        warn "Yahoo Geocoding API error: #{doc['Error']} (#{doc['ErrorMessage']})."
+      end
+    end
+
+    def query_url(query, reverse = false)
+      params = {
+        :location =>  query,
+        :flags => "JXTSR",
+        :gflags => "AC#{'R' if reverse}",
+        :appid => Geocoder::Configuration.yahoo_appid
+      }
+      "http://where.yahooapis.com/geocode?" + params.to_query
+    end
+  end
+end
+
diff --git a/lib/geocoder/results/yahoo.rb b/lib/geocoder/results/yahoo.rb
new file mode 100644
index 00000000..d82a0802
--- /dev/null
+++ b/lib/geocoder/results/yahoo.rb
@@ -0,0 +1,28 @@
+require 'geocoder/results/base'
+
+module Geocoder::Result
+  class Yahoo < Base
+
+    def coordinates
+      [latitude.to_f, longitude.to_f]
+    end
+
+    def address(format = :full)
+      (1..3).to_a.map{ |i| @data["line#{i}"] }.reject{ |i| i.nil? or i == "" }.join(", ")
+    end
+
+    def self.yahoo_attributes
+      %w[quality latitude longitude offsetlat offsetlon radius boundingbox name
+        line1 line2 line3 line4 cross house street xstreet unittype unit postal
+        neighborhood city county state country countrycode statecode countycode
+        level0 level1 level2 level3 level4 level0code level1code level2code
+        timezone areacode uzip hash woeid woetype]
+    end
+
+    yahoo_attributes.each do |a|
+      define_method a do
+        @data[a]
+      end
+    end
+  end
+end
diff --git a/test/fixtures/madison_square_garden.json b/test/fixtures/google_madison_square_garden.json
similarity index 100%
rename from test/fixtures/madison_square_garden.json
rename to test/fixtures/google_madison_square_garden.json
diff --git a/test/fixtures/yahoo_madison_square_garden.json b/test/fixtures/yahoo_madison_square_garden.json
new file mode 100644
index 00000000..6ddcc205
--- /dev/null
+++ b/test/fixtures/yahoo_madison_square_garden.json
@@ -0,0 +1,41 @@
+{
+  "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
+    }]
+  }
+}
diff --git a/test/geocoder_test.rb b/test/geocoder_test.rb
index 27a43afa..df5aaad5 100644
--- a/test/geocoder_test.rb
+++ b/test/geocoder_test.rb
@@ -2,6 +2,11 @@ require 'test_helper'
 
 class GeocoderTest < Test::Unit::TestCase
 
+  def setup
+    Geocoder::Configuration.lookup = :google
+    Geocoder.set_lookup :google
+  end
+
   def test_fetch_coordinates
     v = Venue.new(*venue_params(:msg))
     assert_equal [40.750354, -73.993371], v.fetch_coordinates
@@ -40,4 +45,20 @@ class GeocoderTest < Test::Unit::TestCase
       v.fetch_coordinates
     end
   end
+
+  # --- Yahoo ---
+  def test_yahoo_result_components
+    Geocoder::Configuration.lookup = :yahoo
+    Geocoder.set_lookup :yahoo
+    results = Geocoder.search("Madison Square Garden, New York, NY")
+    assert_equal "10001", results.first.postal
+  end
+
+  def test_yahoo_address_formatting
+    Geocoder::Configuration.lookup = :yahoo
+    Geocoder.set_lookup :yahoo
+    results = Geocoder.search("Madison Square Garden, New York, NY")
+    assert_equal "Madison Square Garden, New York, NY  10001",
+      results.first.address
+  end
 end
diff --git a/test/test_helper.rb b/test/test_helper.rb
index dfc82fa9..2ec28ee2 100644
--- a/test/test_helper.rb
+++ b/test/test_helper.rb
@@ -40,13 +40,13 @@ require "geocoder/lookups/base"
 #
 module Geocoder
   module Lookup
-  class Base
-    private #-----------------------------------------------------------------
-    def fetch_raw_data(query, reverse = false)
-      File.read(File.join("test", "fixtures", "madison_square_garden.json"))
+    class Base
+      private #-----------------------------------------------------------------
+      def fetch_raw_data(query, reverse = false)
+        File.read(File.join("test", "fixtures", "#{Geocoder::Configuration.lookup}_madison_square_garden.json"))
+      end
     end
   end
-  end
 end
 
 ##
-- 
GitLab