lib/geocoder/lookup.rb in rails-geocoder-0.9.7 vs lib/geocoder/lookup.rb in rails-geocoder-0.9.8

- old
+ new

@@ -4,75 +4,87 @@ module Lookup extend self ## # Query Google for the coordinates of the given address. - # Returns array [lat,lon] if found, nil if not found or if network error. # def coordinates(address) - return nil if address.blank? - return nil unless doc = search(address, false) - # blindly use first result (assume it is most accurate) - place = doc['results'].first['geometry']['location'] - ['lat', 'lng'].map{ |i| place[i] } + if (results = search(address)).size > 0 + place = results.first.geometry['location'] + ['lat', 'lng'].map{ |i| place[i] } + end end ## # Query Google for the address of the given coordinates. - # Returns string if found, nil if not found or if network error. # def address(latitude, longitude) - return nil if latitude.blank? || longitude.blank? - return nil unless doc = search("#{latitude},#{longitude}", true) - # blindly use first result (assume it is most accurate) - doc['results'].first['formatted_address'] + if (results = search(latitude, longitude)).size > 0 + results.first.formatted_address + end end - - private # --------------------------------------------------------------- - ## - # Query Google for geographic information about the given phrase. - # Returns a hash representing a valid geocoder response. - # Returns nil if non-200 HTTP response, timeout, or other error. + # Takes a search string (eg: "Mississippi Coast Coliseumf, Biloxi, MS") for + # geocoding, or coordinates (latitude, longitude) for reverse geocoding. + # Returns an array of Geocoder::Result objects, + # or nil if not found or if network error. # - def search(query, reverse = false) - doc = fetch_parsed_response(query, reverse) - doc && doc['status'] == "OK" ? doc : nil + def search(*args) + return nil if args[0].blank? + doc = parsed_response(args.join(","), args.size == 2) + [].tap do |results| + if doc + doc['results'].each{ |r| results << Result.new(r) } + end + end end + + private # --------------------------------------------------------------- + ## # Returns a parsed Google geocoder search result (hash). - # This method is not intended for general use (prefer Geocoder.search). + # Returns nil if non-200 HTTP response, timeout, or other error. # - def fetch_parsed_response(query, reverse = false) - if doc = fetch_raw_response(query, reverse) - ActiveSupport::JSON.decode(doc) + def parsed_response(query, reverse = false) + begin + doc = ActiveSupport::JSON.decode(fetch_data(query, reverse)) + rescue SocketError + warn "Google Geocoding API connection cannot be established." + rescue TimeoutError + warn "Google Geocoding API not responding fast enough " + + "(see Geocoder::Configuration.timeout to set limit)." end + + case doc['status']; when "OK" + doc + when "OVER_QUERY_LIMIT" + warn "Google Geocoding API error: over query limit." + when "REQUEST_DENIED" + warn "Google Geocoding API error: request denied." + when "INVALID_REQUEST" + warn "Google Geocoding API error: invalid request." + end end ## - # Returns a raw Google geocoder search result (JSON). - # This method is not intended for general use (prefer Geocoder.search). + # Fetches a raw Google geocoder search result (JSON string). # - def fetch_raw_response(query, reverse = false) + def fetch_data(query, reverse = false) return nil if query.blank? - - # name parameter based on forward/reverse geocoding - param = reverse ? :latlng : :address - - # build URL - params = { param => query, :sensor => "false" } - url = "http://maps.google.com/maps/api/geocode/json?" + params.to_query - - # query geocoder and make sure it responds quickly - begin - resp = nil - timeout(3) do - Net::HTTP.get_response(URI.parse(url)).body - end - rescue SocketError, TimeoutError - return nil + url = query_url(query, reverse) + timeout(Geocoder::Configuration.timeout) do + Net::HTTP.get_response(URI.parse(url)).body end end + + def query_url(query, reverse = false) + params = { + (reverse ? :latlng : :address) => query, + :sensor => "false" + } + "http://maps.google.com/maps/api/geocode/json?" + params.to_query + end end end +