lib/geokit/geocoders.rb in andre-geokit-1.4.0 vs lib/geokit/geocoders.rb in andre-geokit-1.4.1
- old
+ new
@@ -3,10 +3,13 @@
require 'yaml'
require 'timeout'
require 'logger'
module Geokit
+
+ class TooManyQueriesError < StandardError; end
+
module Inflector
extend self
def titleize(word)
@@ -65,11 +68,11 @@
module Geocoders
@@proxy_addr = nil
@@proxy_port = nil
@@proxy_user = nil
@@proxy_pass = nil
- @@timeout = nil
+ @@request_timeout = nil
@@yahoo = 'REPLACE_WITH_YOUR_YAHOO_KEY'
@@google = 'REPLACE_WITH_YOUR_GOOGLE_KEY'
@@geocoder_us = false
@@geocoder_ca = false
@@geonames = false
@@ -79,11 +82,11 @@
@@logger.level=Logger::INFO
@@domain = nil
def self.__define_accessors
class_variables.each do |v|
- sym = v.delete("@").to_sym
+ sym = v.to_s.delete("@").to_sym
unless self.respond_to? sym
module_eval <<-EOS, __FILE__, __LINE__
def self.#{sym}
value = if defined?(#{sym.to_s.upcase})
#{sym.to_s.upcase}
@@ -131,11 +134,11 @@
return res.success? ? res : GeoLoc.new
end
# Call the geocoder service using the timeout if configured.
def self.call_geocoder_service(url)
- timeout(Geokit::Geocoders::timeout) { return self.do_get(url) } if Geokit::Geocoders::timeout
+ Timeout::timeout(Geokit::Geocoders::request_timeout) { return self.do_get(url) } if Geokit::Geocoders::request_timeout
return self.do_get(url)
rescue TimeoutError
return nil
end
@@ -160,12 +163,11 @@
req = Net::HTTP::Get.new(url)
req.basic_auth(uri.user, uri.password) if uri.userinfo
res = Net::HTTP::Proxy(GeoKit::Geocoders::proxy_addr,
GeoKit::Geocoders::proxy_port,
GeoKit::Geocoders::proxy_user,
- GeoKit::Geocoders::proxy_pass).start(uri.host, uri.port) { |http| http.request(req) }
-
+ GeoKit::Geocoders::proxy_pass).start(uri.host, uri.port) { |http| http.get(uri.path + "?" + uri.query) }
return res
end
# Adds subclass' geocode method making it conveniently available through
# the base class.
@@ -461,18 +463,23 @@
# geolocs onto "geoloc.all"
geoloc.all.push(extracted_geoloc)
end
end
return geoloc
- else
+ elsif doc.elements['//kml/Response/Status/code'].text == '620'
+ raise Geokit::TooManyQueriesError
+ else
logger.info "Google was unable to geocode address: "+address
return GeoLoc.new
end
- rescue
- logger.error "Caught an error during Google geocoding call: "+$!
- return GeoLoc.new
+ rescue Geokit::TooManyQueriesError
+ # re-raise because of other rescue
+ raise Geokit::TooManyQueriesError, "Google returned a 620 status, too many queries. The given key has gone over the requests limit in the 24 hour period or has submitted too many requests in too short a period of time. If you're sending multiple requests in parallel or in a tight loop, use a timer or pause in your code to make sure you don't send the requests too quickly."
+ rescue
+ logger.error "Caught an error during Google geocoding call: "+$!
+ return GeoLoc.new
end
# extracts a single geoloc from a //placemark element in the google results xml
def self.extract_placemark(doc)
res = GeoLoc.new
@@ -485,13 +492,16 @@
res.provider='google'
#extended -- false if not not available
res.city = doc.elements['.//LocalityName'].text if doc.elements['.//LocalityName']
res.state = doc.elements['.//AdministrativeAreaName'].text if doc.elements['.//AdministrativeAreaName']
+ res.province = doc.elements['.//SubAdministrativeAreaName'].text if doc.elements['.//SubAdministrativeAreaName']
res.full_address = doc.elements['.//address'].text if doc.elements['.//address'] # google provides it
res.zip = doc.elements['.//PostalCodeNumber'].text if doc.elements['.//PostalCodeNumber']
res.street_address = doc.elements['.//ThoroughfareName'].text if doc.elements['.//ThoroughfareName']
+ res.country = doc.elements['.//CountryName'].text if doc.elements['.//CountryName']
+ res.district = doc.elements['.//DependentLocalityName'].text if doc.elements['.//DependentLocalityName']
# Translate accuracy into Yahoo-style token address, street, zip, zip+4, city, state, country
# For Google, 1=low accuracy, 8=high accuracy
address_details=doc.elements['.//*[local-name() = "AddressDetails"]']
res.accuracy = address_details ? address_details.attributes['Accuracy'].to_i : 0
res.precision=%w{unknown country state state city zip zip+4 street address building}[res.accuracy]
@@ -502,11 +512,11 @@
[suggested_bounds.attributes['south'], suggested_bounds.attributes['west']],
[suggested_bounds.attributes['north'], suggested_bounds.attributes['east']])
end
res.success=true
-
- return res
+
+ return res
end
end
# -------------------------------------------------------------------------------------------