From 302dfca6805ff3731e603127e2977e709f13bbc5 Mon Sep 17 00:00:00 2001
From: Alex Reisner <alex@alexreisner.com>
Date: Fri, 4 Mar 2011 17:30:56 -0500
Subject: [PATCH] Add geocode method to model.

This is a generic method for fetching geo data and storing it in the
object (now used by fetch_coordinates and fetch_address).
---
 lib/geocoder/active_record.rb | 65 ++++++++++++++++++++++-------------
 1 file changed, 41 insertions(+), 24 deletions(-)

diff --git a/lib/geocoder/active_record.rb b/lib/geocoder/active_record.rb
index 1ddd3c3b..fdb38c73 100644
--- a/lib/geocoder/active_record.rb
+++ b/lib/geocoder/active_record.rb
@@ -178,24 +178,47 @@ module Geocoder
       self.class.near(read_coordinates, radius, options)
     end
 
+    ##
+    # Look up geographic data based on object attributes,
+    # and do something with it (requires a block).
+    #
+    def geocode(reverse = false, &block)
+      if reverse
+        lat_attr = self.class.geocoder_options[:latitude]
+        lon_attr = self.class.geocoder_options[:longitude]
+        unless lat_attr.is_a?(Symbol) and lon_attr.is_a?(Symbol)
+          raise Geocoder::ConfigurationError,
+            "You are attempting to fetch an address but have not specified " +
+            "attributes which provide coordinates for the object."
+        end
+        args = [send(lat_attr), send(lon_attr)]
+      else
+        address_method = self.class.geocoder_options[:user_address]
+        unless address_method.is_a? Symbol
+          raise Geocoder::ConfigurationError,
+            "You are attempting to geocode an object but have not specified " +
+            "a method which provides an address to search for."
+        end
+        args = [send(address_method)]
+      end
+      if result = Geocoder.search(*args).first
+        block.call(result)
+      end
+    end
+
     ##
     # Fetch coordinates and assign +latitude+ and +longitude+. Also returns
     # coordinates as an array: <tt>[lat, lon]</tt>.
     #
     def fetch_coordinates(save = false)
-      address_method = self.class.geocoder_options[:user_address]
-      unless address_method.is_a? Symbol
-        raise Geocoder::ConfigurationError,
-          "You are attempting to fetch coordinates but have not specified " +
-          "a method which provides an address for the object."
-      end
-      coords = Geocoder.coordinates(send(address_method))
-      unless coords.blank?
-        method = (save ? "update" : "write") + "_attribute"
-        send method, self.class.geocoder_options[:latitude],  coords[0]
-        send method, self.class.geocoder_options[:longitude], coords[1]
+      geocode do |r|
+        unless r.latitude.nil? or r.longitude.nil?
+          method = (save ? "update" : "write") + "_attribute"
+          send method, self.class.geocoder_options[:latitude],  r.latitude
+          send method, self.class.geocoder_options[:longitude], r.longitude
+        end
+        r.coordinates
       end
-      coords
     end
 
     ##
@@ -210,19 +233,13 @@ module Geocoder
     # address as a string.
     #
     def fetch_address(save = false)
-      lat_attr = self.class.geocoder_options[:latitude]
-      lon_attr = self.class.geocoder_options[:longitude]
-      unless lat_attr.is_a?(Symbol) and lon_attr.is_a?(Symbol)
-        raise Geocoder::ConfigurationError,
-          "You are attempting to fetch an address but have not specified " +
-          "attributes which provide coordinates for the object."
-      end
-      address = Geocoder.address(send(lat_attr), send(lon_attr))
-      unless address.blank?
-        method = (save ? "update" : "write") + "_attribute"
-        send method, self.class.geocoder_options[:fetched_address], address
+      geocode(true) do |r|
+        unless r.address.nil?
+          method = (save ? "update" : "write") + "_attribute"
+          send method, self.class.geocoder_options[:fetched_address], r.address
+        end
+        r.address
       end
-      address
     end
 
     ##
-- 
GitLab