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
+