From 4b4a686d3f1fd1520e51376839d1696684c8f8a6 Mon Sep 17 00:00:00 2001
From: Alex Reisner <alex@alexreisner.com>
Date: Thu, 3 Feb 2011 22:49:50 -0500
Subject: [PATCH] Add Geocoder::Result and Geocoder.search.

---
 README.rdoc            |  2 --
 lib/geocoder.rb        | 19 +++++++++++++++++++
 lib/geocoder/lookup.rb |  8 ++++++--
 lib/geocoder/result.rb | 42 ++++++++++++++++++++++++++++++++++++++++++
 test/geocoder_test.rb  |  6 ++++++
 5 files changed, 73 insertions(+), 4 deletions(-)
 create mode 100644 lib/geocoder/result.rb

diff --git a/README.rdoc b/README.rdoc
index 426dc407..9e6e0d69 100644
--- a/README.rdoc
+++ b/README.rdoc
@@ -178,8 +178,6 @@ If anyone has a more elegant solution to this problem I am very interested in se
   * also need to make sure 'mysql2' is supported
 * make 'near' scope work with AR associations
   * http://stackoverflow.com/questions/3266358/geocoder-rails-plugin-near-search-problem-with-activerecord
-* unobtrusively add ability to get a result with more data (Geocoder object?)
-  * the default usage should remain dead simple
 
 
 Copyright (c) 2009-11 Alex Reisner, released under the MIT license
diff --git a/lib/geocoder.rb b/lib/geocoder.rb
index fee7fabb..918163cc 100644
--- a/lib/geocoder.rb
+++ b/lib/geocoder.rb
@@ -1,7 +1,26 @@
 require "geocoder/calculations"
 require "geocoder/lookup"
+require "geocoder/result"
 require "geocoder/active_record"
 
+module Geocoder
+  extend self
+
+  ##
+  # Takes a search string (eg: "Mississippi Coast Coliseumf, Biloxi, MS") for
+  # geocoding, or coordinates (latitude, longitude) for reverse geocoding.
+  # Returns a Geocoder::Result object.
+  #
+  def search(*args)
+    if args.size == 2
+      Lookup.search(args[0], args[1], true)
+    else
+      Lookup.search(args[0], false)
+    end
+  end
+end
+
+
 ##
 # Add geocoded_by method to ActiveRecord::Base so Geocoder is accessible.
 #
diff --git a/lib/geocoder/lookup.rb b/lib/geocoder/lookup.rb
index fd2ae65f..96b8d16e 100644
--- a/lib/geocoder/lookup.rb
+++ b/lib/geocoder/lookup.rb
@@ -29,10 +29,14 @@ module Geocoder
 
     ##
     # Query Google for geographic information about the given phrase.
-    # Returns a Result object containing all data returned by Google.
+    # Returns an array of Geocoder::Result objects.
     #
     def search(query, reverse = false)
-      # TODO
+      [].tap do |results|
+        if doc = parsed_response(query, reverse)
+          doc['results'].each{ |r| results << Result.new(r) }
+        end
+      end
     end
 
 
diff --git a/lib/geocoder/result.rb b/lib/geocoder/result.rb
new file mode 100644
index 00000000..e63f2263
--- /dev/null
+++ b/lib/geocoder/result.rb
@@ -0,0 +1,42 @@
+module Geocoder
+  class Result
+    attr_accessor :data
+
+    ##
+    # Takes a hash of result data from a parsed Google result document.
+    #
+    def initialize(data)
+      @data = data
+    end
+
+    def types
+      @data['types']
+    end
+
+    def formatted_address
+      @data['formatted_address']
+    end
+
+    def address_components
+      @data['address_components']
+    end
+
+    ##
+    # Get address components of a given type. Valid types are defined in
+    # Google's Geocoding API documentation and include (among others):
+    #
+    #   :street_number
+    #   :locality
+    #   :neighborhood
+    #   :route
+    #   :postal_code
+    #
+    def address_components_of_type(type)
+      address_components.select{ |c| c['types'].include?(type.to_s) }
+    end
+
+    def geometry
+      @data['geometry']
+    end
+  end
+end
diff --git a/test/geocoder_test.rb b/test/geocoder_test.rb
index 83b4c51a..7b8c0ff5 100644
--- a/test/geocoder_test.rb
+++ b/test/geocoder_test.rb
@@ -27,4 +27,10 @@ class GeocoderTest < Test::Unit::TestCase
       l.fetch_coordinates
     end
   end
+
+  def test_result_address_components_of_type
+    results = Geocoder::Lookup.search("Madison Square Garden, New York, NY")
+    assert_equal "Manhattan",
+      results.first.address_components_of_type(:sublocality).first['long_name']
+  end
 end
-- 
GitLab