geokit-premier 0.0.7 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -11,13 +11,13 @@ module Geokit
11
11
  class TooManyQueriesError < StandardError; end
12
12
 
13
13
  module Inflector
14
-
14
+
15
15
  extend self
16
-
16
+
17
17
  def titleize(word)
18
18
  humanize(underscore(word)).gsub(/\b([a-z])/u) { $1.capitalize }
19
19
  end
20
-
20
+
21
21
  def underscore(camel_cased_word)
22
22
  camel_cased_word.to_s.gsub(/::/, '/').
23
23
  gsub(/([A-Z]+)([A-Z][a-z])/u,'\1_\2').
@@ -25,52 +25,52 @@ module Geokit
25
25
  tr("-", "_").
26
26
  downcase
27
27
  end
28
-
28
+
29
29
  def humanize(lower_case_and_underscored_word)
30
30
  lower_case_and_underscored_word.to_s.gsub(/_id$/, "").gsub(/_/, " ").capitalize
31
31
  end
32
-
32
+
33
33
  def snake_case(s)
34
34
  return s.downcase if s =~ /^[A-Z]+$/u
35
35
  s.gsub(/([A-Z]+)(?=[A-Z][a-z]?)|\B[A-Z]/u, '_\&') =~ /_*(.*)/
36
36
  return $+.downcase
37
-
37
+
38
38
  end
39
-
39
+
40
40
  def url_escape(s)
41
41
  URI.escape(s)
42
42
  end
43
-
43
+
44
44
  def camelize(str)
45
45
  str.split('_').map {|w| w.capitalize}.join
46
46
  end
47
- end
48
-
47
+ end
48
+
49
49
  # Contains a range of geocoders:
50
- #
51
- # ### "regular" address geocoders
50
+ #
51
+ # ### "regular" address geocoders
52
52
  # * Yahoo Geocoder - requires an API key.
53
53
  # * Geocoder.us - may require authentication if performing more than the free request limit.
54
54
  # * Geocoder.ca - for Canada; may require authentication as well.
55
55
  # * Geonames - a free geocoder
56
56
  #
57
- # ### address geocoders that also provide reverse geocoding
57
+ # ### address geocoders that also provide reverse geocoding
58
58
  # * Google Geocoder - requires an API key.
59
- #
60
- # ### IP address geocoders
59
+ #
60
+ # ### IP address geocoders
61
61
  # * IP Geocoder - geocodes an IP address using hostip.info's web service.
62
62
  # * Geoplugin.net -- another IP address geocoder
63
63
  #
64
64
  # ### The Multigeocoder
65
65
  # * Multi Geocoder - provides failover for the physical location geocoders.
66
- #
66
+ #
67
67
  # Some of these geocoders require configuration. You don't have to provide it here. See the README.
68
68
  module Geocoders
69
69
  @@proxy_addr = nil
70
70
  @@proxy_port = nil
71
71
  @@proxy_user = nil
72
72
  @@proxy_pass = nil
73
- @@request_timeout = nil
73
+ @@request_timeout = nil
74
74
  @@yahoo = 'REPLACE_WITH_YOUR_YAHOO_KEY'
75
75
  @@google = 'REPLACE_WITH_YOUR_GOOGLE_KEY'
76
76
  @@google_client_id = nil #only used for premier accounts
@@ -83,9 +83,9 @@ module Geokit
83
83
  @@logger=Logger.new(STDOUT)
84
84
  @@logger.level=Logger::INFO
85
85
  @@domain = nil
86
-
86
+
87
87
  def self.__define_accessors
88
- class_variables.each do |v|
88
+ class_variables.each do |v|
89
89
  sym = v.to_s.delete("@").to_sym
90
90
  unless self.respond_to? sym
91
91
  module_eval <<-EOS, __FILE__, __LINE__
@@ -100,7 +100,7 @@ module Geokit
100
100
  end
101
101
  value
102
102
  end
103
-
103
+
104
104
  def self.#{sym}=(obj)
105
105
  @@#{sym} = obj
106
106
  end
@@ -110,38 +110,38 @@ module Geokit
110
110
  end
111
111
 
112
112
  __define_accessors
113
-
113
+
114
114
  # Error which is thrown in the event a geocoding error occurs.
115
115
  class GeocodeError < StandardError; end
116
116
 
117
117
  # -------------------------------------------------------------------------------------------
118
118
  # Geocoder Base class -- every geocoder should inherit from this
119
- # -------------------------------------------------------------------------------------------
120
-
119
+ # -------------------------------------------------------------------------------------------
120
+
121
121
  # The Geocoder base class which defines the interface to be used by all
122
122
  # other geocoders.
123
- class Geocoder
123
+ class Geocoder
124
124
  # Main method which calls the do_geocode template method which subclasses
125
125
  # are responsible for implementing. Returns a populated GeoLoc or an
126
126
  # empty one with a failed success code.
127
- def self.geocode(address, options = {})
127
+ def self.geocode(address, options = {})
128
128
  res = do_geocode(address, options)
129
129
  return res.nil? ? GeoLoc.new : res
130
- end
130
+ end
131
131
  # Main method which calls the do_reverse_geocode template method which subclasses
132
132
  # are responsible for implementing. Returns a populated GeoLoc or an
133
133
  # empty one with a failed success code.
134
134
  def self.reverse_geocode(latlng)
135
135
  res = do_reverse_geocode(latlng)
136
- return res.success? ? res : GeoLoc.new
136
+ return res.success? ? res : GeoLoc.new
137
137
  end
138
-
138
+
139
139
  # Call the geocoder service using the timeout if configured.
140
140
  def self.call_geocoder_service(url)
141
- Timeout::timeout(Geokit::Geocoders::request_timeout) { return self.do_get(url) } if Geokit::Geocoders::request_timeout
141
+ Timeout::timeout(Geokit::Geocoders::request_timeout) { return self.do_get(url) } if Geokit::Geocoders::request_timeout
142
142
  return self.do_get(url)
143
143
  rescue TimeoutError
144
- return nil
144
+ return nil
145
145
  end
146
146
 
147
147
  # Not all geocoders can do reverse geocoding. So, unless the subclass explicitly overrides this method,
@@ -157,7 +157,7 @@ module Geokit
157
157
  url_to_sign = uri.path + "?" + uri.query
158
158
  decoded_key = Geocoder.urlsafe_decode64(private_key)
159
159
 
160
- sha1_digest = OpenSSL::Digest::Digest.new('sha1')
160
+ sha1_digest = OpenSSL::Digest.new('sha1')
161
161
  signature = OpenSSL::HMAC.digest(sha1_digest,decoded_key,url_to_sign)
162
162
  encoded_signature = Geocoder.urlsafe_encode64(signature)
163
163
  signed_url = "#{uri.scheme}://#{uri.host}#{uri.path}?#{uri.query}&signature=#{encoded_signature}".strip!
@@ -181,14 +181,14 @@ module Geokit
181
181
 
182
182
  protected
183
183
 
184
- def self.logger()
184
+ def self.logger()
185
185
  Geokit::Geocoders::logger
186
186
  end
187
-
187
+
188
188
  private
189
-
189
+
190
190
  # Wraps the geocoder call around a proxy if necessary.
191
- def self.do_get(url)
191
+ def self.do_get(url)
192
192
  uri = URI.parse(url)
193
193
  req = Net::HTTP::Get.new(url)
194
194
  req.basic_auth(uri.user, uri.password) if uri.userinfo
@@ -198,8 +198,8 @@ module Geokit
198
198
  GeoKit::Geocoders::proxy_pass).start(uri.host, uri.port) { |http| http.get(uri.path + "?" + uri.query) }
199
199
  return res
200
200
  end
201
-
202
- # Adds subclass' geocode method making it conveniently available through
201
+
202
+ # Adds subclass' geocode method making it conveniently available through
203
203
  # the base class.
204
204
  def self.inherited(clazz)
205
205
  class_name = clazz.name.split('::').last
@@ -214,10 +214,10 @@ module Geokit
214
214
 
215
215
  # -------------------------------------------------------------------------------------------
216
216
  # "Regular" Address geocoders
217
- # -------------------------------------------------------------------------------------------
218
-
217
+ # -------------------------------------------------------------------------------------------
218
+
219
219
  # Geocoder CA geocoder implementation. Requires the Geokit::Geocoders::GEOCODER_CA variable to
220
- # contain true or false based upon whether authentication is to occur. Conforms to the
220
+ # contain true or false based upon whether authentication is to occur. Conforms to the
221
221
  # interface set by the Geocoder class.
222
222
  #
223
223
  # Returns a response like:
@@ -239,15 +239,15 @@ module Geokit
239
239
  xml = res.body
240
240
  logger.debug "Geocoder.ca geocoding. Address: #{address}. Result: #{xml}"
241
241
  # Parse the document.
242
- doc = REXML::Document.new(xml)
242
+ doc = REXML::Document.new(xml)
243
243
  address.lat = doc.elements['//latt'].text
244
244
  address.lng = doc.elements['//longt'].text
245
245
  address.success = true
246
246
  return address
247
247
  rescue
248
248
  logger.error "Caught an error during Geocoder.ca geocoding call: "+$!
249
- return GeoLoc.new
250
- end
249
+ return GeoLoc.new
250
+ end
251
251
 
252
252
  # Formats the request in the format acceptable by the CA geocoder.
253
253
  def self.construct_request(location)
@@ -265,60 +265,60 @@ module Geokit
265
265
  def self.add_ampersand(url)
266
266
  url && url.length > 0 ? "&" : ""
267
267
  end
268
- end
269
-
268
+ end
269
+
270
270
  # Geocoder Us geocoder implementation. Requires the Geokit::Geocoders::GEOCODER_US variable to
271
- # contain true or false based upon whether authentication is to occur. Conforms to the
271
+ # contain true or false based upon whether authentication is to occur. Conforms to the
272
272
  # interface set by the Geocoder class.
273
273
  class UsGeocoder < Geocoder
274
274
 
275
275
  private
276
276
  def self.do_geocode(address, options = {})
277
277
  address_str = address.is_a?(GeoLoc) ? address.to_geocodeable_s : address
278
-
278
+
279
279
  query = (address_str =~ /^\d{5}(?:-\d{4})?$/ ? "zip" : "address") + "=#{Geokit::Inflector::url_escape(address_str)}"
280
- url = if GeoKit::Geocoders::geocoder_us
280
+ url = if GeoKit::Geocoders::geocoder_us
281
281
  "http://#{GeoKit::Geocoders::geocoder_us}@geocoder.us/member/service/csv/geocode"
282
282
  else
283
283
  "http://geocoder.us/service/csv/geocode"
284
284
  end
285
-
286
- url = "#{url}?#{query}"
285
+
286
+ url = "#{url}?#{query}"
287
287
  res = self.call_geocoder_service(url)
288
-
288
+
289
289
  return GeoLoc.new if !res.is_a?(Net::HTTPSuccess)
290
290
  data = res.body
291
291
  logger.debug "Geocoder.us geocoding. Address: #{address}. Result: #{data}"
292
292
  array = data.chomp.split(',')
293
-
293
+
294
294
  if array.length == 5
295
295
  res=GeoLoc.new
296
296
  res.lat,res.lng,res.city,res.state,res.zip=array
297
297
  res.country_code='US'
298
298
  res.success=true
299
299
  return res
300
- elsif array.length == 6
301
- res=GeoLoc.new
300
+ elsif array.length == 6
301
+ res=GeoLoc.new
302
302
  res.lat,res.lng,res.street_address,res.city,res.state,res.zip=array
303
303
  res.country_code='US'
304
- res.success=true
304
+ res.success=true
305
305
  return res
306
- else
306
+ else
307
307
  logger.info "geocoder.us was unable to geocode address: "+address
308
- return GeoLoc.new
308
+ return GeoLoc.new
309
309
  end
310
- rescue
310
+ rescue
311
311
  logger.error "Caught an error during geocoder.us geocoding call: "+$!
312
312
  return GeoLoc.new
313
313
 
314
314
  end
315
315
  end
316
-
316
+
317
317
  # Yahoo geocoder implementation. Requires the Geokit::Geocoders::YAHOO variable to
318
318
  # contain a Yahoo API key. Conforms to the interface set by the Geocoder class.
319
319
  class YahooGeocoder < Geocoder
320
320
 
321
- private
321
+ private
322
322
 
323
323
  # Template method which does the geocode lookup.
324
324
  def self.do_geocode(address, options = {})
@@ -333,11 +333,11 @@ module Geokit
333
333
  if doc.elements['//ResultSet']
334
334
  res=GeoLoc.new
335
335
 
336
- #basic
336
+ #basic
337
337
  res.lat=doc.elements['//Latitude'].text
338
338
  res.lng=doc.elements['//Longitude'].text
339
339
  res.country_code=doc.elements['//Country'].text
340
- res.provider='yahoo'
340
+ res.provider='yahoo'
341
341
 
342
342
  #extended - false if not available
343
343
  res.city=doc.elements['//City'].text if doc.elements['//City'] && doc.elements['//City'].text != nil
@@ -349,12 +349,12 @@ module Geokit
349
349
  res.accuracy=%w{unknown country state state city zip zip+4 street address building}.index(res.precision)
350
350
  res.success=true
351
351
  return res
352
- else
352
+ else
353
353
  logger.info "Yahoo was unable to geocode address: "+address
354
354
  return GeoLoc.new
355
- end
355
+ end
356
356
 
357
- rescue
357
+ rescue
358
358
  logger.info "Caught an error during Yahoo geocoding call: "+$!
359
359
  return GeoLoc.new
360
360
  end
@@ -364,47 +364,47 @@ module Geokit
364
364
  # http://www.geonames.org
365
365
  class GeonamesGeocoder < Geocoder
366
366
 
367
- private
368
-
367
+ private
368
+
369
369
  # Template method which does the geocode lookup.
370
370
  def self.do_geocode(address, options = {})
371
371
  address_str = address.is_a?(GeoLoc) ? address.to_geocodeable_s : address
372
372
  # geonames need a space seperated search string
373
373
  address_str.gsub!(/,/, " ")
374
374
  params = "/postalCodeSearch?placename=#{Geokit::Inflector::url_escape(address_str)}&maxRows=10"
375
-
375
+
376
376
  if(GeoKit::Geocoders::geonames)
377
377
  url = "http://ws.geonames.net#{params}&username=#{GeoKit::Geocoders::geonames}"
378
378
  else
379
379
  url = "http://ws.geonames.org#{params}"
380
380
  end
381
-
381
+
382
382
  res = self.call_geocoder_service(url)
383
-
383
+
384
384
  return GeoLoc.new if !res.is_a?(Net::HTTPSuccess)
385
-
385
+
386
386
  xml=res.body
387
387
  logger.debug "Geonames geocoding. Address: #{address}. Result: #{xml}"
388
388
  doc=REXML::Document.new(xml)
389
-
389
+
390
390
  if(doc.elements['//geonames/totalResultsCount'].text.to_i > 0)
391
391
  res=GeoLoc.new
392
-
392
+
393
393
  # only take the first result
394
394
  res.lat=doc.elements['//code/lat'].text if doc.elements['//code/lat']
395
395
  res.lng=doc.elements['//code/lng'].text if doc.elements['//code/lng']
396
396
  res.country_code=doc.elements['//code/countryCode'].text if doc.elements['//code/countryCode']
397
- res.provider='genomes'
397
+ res.provider='genomes'
398
398
  res.city=doc.elements['//code/name'].text if doc.elements['//code/name']
399
399
  res.state=doc.elements['//code/adminName1'].text if doc.elements['//code/adminName1']
400
400
  res.zip=doc.elements['//code/postalcode'].text if doc.elements['//code/postalcode']
401
401
  res.success=true
402
402
  return res
403
- else
403
+ else
404
404
  logger.info "Geonames was unable to geocode address: "+address
405
405
  return GeoLoc.new
406
406
  end
407
-
407
+
408
408
  rescue
409
409
  logger.error "Caught an error during Geonames geocoding call: "+$!
410
410
  end
@@ -418,18 +418,18 @@ module Geokit
418
418
  # contain a Google API key. Conforms to the interface set by the Geocoder class.
419
419
  class GoogleGeocoder < Geocoder
420
420
 
421
- private
422
-
421
+ private
422
+
423
423
  # Template method which does the reverse-geocode lookup.
424
- def self.do_reverse_geocode(latlng)
424
+ def self.do_reverse_geocode(latlng)
425
425
  latlng=LatLng.normalize(latlng)
426
426
  res = self.call_geocoder_service("http://maps.google.com/maps/geo?ll=#{Geokit::Inflector::url_escape(latlng.ll)}&output=xml&key=#{Geokit::Geocoders::google}&oe=utf-8")
427
427
  # res = Net::HTTP.get_response(URI.parse("http://maps.google.com/maps/geo?ll=#{Geokit::Inflector::url_escape(address_str)}&output=xml&key=#{Geokit::Geocoders::google}&oe=utf-8"))
428
428
  return GeoLoc.new unless (res.is_a?(Net::HTTPSuccess) || res.is_a?(Net::HTTPOK))
429
429
  xml = res.body
430
430
  logger.debug "Google reverse-geocoding. LL: #{latlng}. Result: #{xml}"
431
- return self.xml2GeoLoc(xml)
432
- end
431
+ return self.xml2GeoLoc(xml)
432
+ end
433
433
 
434
434
  # Template method which does the geocode lookup.
435
435
  #
@@ -438,7 +438,7 @@ module Geokit
438
438
  # ==== OPTIONS
439
439
  # * :bias - This option makes the Google Geocoder return results biased to a particular
440
440
  # country or viewport. Country code biasing is achieved by passing the ccTLD
441
- # ('uk' for .co.uk, for example) as a :bias value. For a list of ccTLD's,
441
+ # ('uk' for .co.uk, for example) as a :bias value. For a list of ccTLD's,
442
442
  # look here: http://en.wikipedia.org/wiki/CcTLD. By default, the geocoder
443
443
  # will be biased to results within the US (ccTLD .com).
444
444
  #
@@ -461,9 +461,9 @@ module Geokit
461
461
  return GeoLoc.new if !res.is_a?(Net::HTTPSuccess)
462
462
  xml = res.body
463
463
  logger.debug "Google geocoding. Address: #{address}. Result: #{xml}"
464
- return self.xml2GeoLoc(xml, address)
464
+ return self.xml2GeoLoc(xml, address)
465
465
  end
466
-
466
+
467
467
  # Determine the Google API url based on the google api key, or based on the client / private key for premier users
468
468
  def self.geocode_url(address,options = {})
469
469
  bias_str = options[:bias] ? construct_bias_string_from_options(options[:bias]) : ''
@@ -476,8 +476,8 @@ module Geokit
476
476
  "http://maps.google.com/maps/geo?q=#{Geokit::Inflector::url_escape(address_str)}&output=xml#{bias_str}&key=#{Geokit::Geocoders::google}&oe=utf-8"
477
477
  end
478
478
  end
479
-
480
-
479
+
480
+
481
481
  def self.construct_bias_string_from_options(bias)
482
482
  if bias.is_a?(String) or bias.is_a?(Symbol)
483
483
  # country code biasing
@@ -487,24 +487,24 @@ module Geokit
487
487
  "&ll=#{bias.center.ll}&spn=#{bias.to_span.ll}"
488
488
  end
489
489
  end
490
-
490
+
491
491
  def self.xml2GeoLoc(xml, address="")
492
492
  doc=REXML::Document.new(xml)
493
493
 
494
494
  if doc.elements['//kml/Response/Status/code'].text == '200'
495
495
  geoloc = nil
496
- # Google can return multiple results as //Placemark elements.
496
+ # Google can return multiple results as //Placemark elements.
497
497
  # iterate through each and extract each placemark as a geoloc
498
498
  doc.each_element('//Placemark') do |e|
499
499
  extracted_geoloc = extract_placemark(e) # g is now an instance of GeoLoc
500
- if geoloc.nil?
500
+ if geoloc.nil?
501
501
  # first time through, geoloc is still nil, so we make it the geoloc we just extracted
502
- geoloc = extracted_geoloc
502
+ geoloc = extracted_geoloc
503
503
  else
504
- # second (and subsequent) iterations, we push additional
505
- # geolocs onto "geoloc.all"
506
- geoloc.all.push(extracted_geoloc)
507
- end
504
+ # second (and subsequent) iterations, we push additional
505
+ # geolocs onto "geoloc.all"
506
+ geoloc.all.push(extracted_geoloc)
507
+ end
508
508
  end
509
509
  return geoloc
510
510
  elsif doc.elements['//kml/Response/Status/code'].text == '620'
@@ -520,7 +520,7 @@ module Geokit
520
520
  rescue
521
521
  logger.error "Caught an error during Google geocoding call: "+$!
522
522
  return GeoLoc.new
523
- end
523
+ end
524
524
 
525
525
  # extracts a single geoloc from a //placemark element in the google results xml
526
526
  def self.extract_placemark(doc)
@@ -547,14 +547,14 @@ module Geokit
547
547
  address_details=doc.elements['.//*[local-name() = "AddressDetails"]']
548
548
  res.accuracy = address_details ? address_details.attributes['Accuracy'].to_i : 0
549
549
  res.precision=%w{unknown country state state city zip zip+4 street address building}[res.accuracy]
550
-
550
+
551
551
  # google returns a set of suggested boundaries for the geocoded result
552
- if suggested_bounds = doc.elements['//LatLonBox']
552
+ if suggested_bounds = doc.elements['//LatLonBox']
553
553
  res.suggested_bounds = Bounds.normalize(
554
- [suggested_bounds.attributes['south'], suggested_bounds.attributes['west']],
554
+ [suggested_bounds.attributes['south'], suggested_bounds.attributes['west']],
555
555
  [suggested_bounds.attributes['north'], suggested_bounds.attributes['east']])
556
556
  end
557
-
557
+
558
558
  res.success=true
559
559
 
560
560
  return res
@@ -565,11 +565,11 @@ module Geokit
565
565
  # -------------------------------------------------------------------------------------------
566
566
  # IP Geocoders
567
567
  # -------------------------------------------------------------------------------------------
568
-
568
+
569
569
  # Provides geocoding based upon an IP address. The underlying web service is geoplugin.net
570
570
  class GeoPluginGeocoder < Geocoder
571
571
  private
572
-
572
+
573
573
  def self.do_geocode(ip, options = {})
574
574
  return GeoLoc.new unless /^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})?$/.match(ip)
575
575
  response = self.call_geocoder_service("http://www.geoplugin.net/xml.gp?ip=#{ip}")
@@ -596,7 +596,7 @@ module Geokit
596
596
  # Provides geocoding based upon an IP address. The underlying web service is a hostip.info
597
597
  # which sources their data through a combination of publicly available information as well
598
598
  # as community contributions.
599
- class IpGeocoder < Geocoder
599
+ class IpGeocoder < Geocoder
600
600
 
601
601
  # A number of non-routable IP ranges.
602
602
  #
@@ -619,11 +619,11 @@ module Geokit
619
619
  IPAddr.new('240.0.0.0/4') # Reserved for future use
620
620
  ].freeze
621
621
 
622
- private
622
+ private
623
623
 
624
624
  # Given an IP address, returns a GeoLoc instance which contains latitude,
625
- # longitude, city, and country code. Sets the success attribute to false if the ip
626
- # parameter does not match an ip address.
625
+ # longitude, city, and country code. Sets the success attribute to false if the ip
626
+ # parameter does not match an ip address.
627
627
  def self.do_geocode(ip, options = {})
628
628
  return GeoLoc.new unless /^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})?$/.match(ip)
629
629
  return GeoLoc.new if self.private_ip_address?(ip)
@@ -649,7 +649,7 @@ module Geokit
649
649
  res.provider = 'hostip'
650
650
  res.city, res.state = yaml['City'].split(', ')
651
651
  country, res.country_code = yaml['Country'].split(' (')
652
- res.lat = yaml['Latitude']
652
+ res.lat = yaml['Latitude']
653
653
  res.lng = yaml['Longitude']
654
654
  res.country_code.chop!
655
655
  res.success = !(res.city =~ /\(.+\)/)
@@ -665,33 +665,33 @@ module Geokit
665
665
  return NON_ROUTABLE_IP_RANGES.any? { |range| range.include?(ip) }
666
666
  end
667
667
  end
668
-
668
+
669
669
  # -------------------------------------------------------------------------------------------
670
670
  # The Multi Geocoder
671
- # -------------------------------------------------------------------------------------------
672
-
671
+ # -------------------------------------------------------------------------------------------
672
+
673
673
  # Provides methods to geocode with a variety of geocoding service providers, plus failover
674
674
  # among providers in the order you configure. When 2nd parameter is set 'true', perform
675
675
  # ip location lookup with 'address' as the ip address.
676
- #
676
+ #
677
677
  # Goal:
678
678
  # - homogenize the results of multiple geocoders
679
- #
679
+ #
680
680
  # Limitations:
681
681
  # - currently only provides the first result. Sometimes geocoders will return multiple results.
682
682
  # - currently discards the "accuracy" component of the geocoding calls
683
- class MultiGeocoder < Geocoder
683
+ class MultiGeocoder < Geocoder
684
684
 
685
685
  private
686
- # This method will call one or more geocoders in the order specified in the
686
+ # This method will call one or more geocoders in the order specified in the
687
687
  # configuration until one of the geocoders work.
688
- #
688
+ #
689
689
  # The failover approach is crucial for production-grade apps, but is rarely used.
690
- # 98% of your geocoding calls will be successful with the first call
690
+ # 98% of your geocoding calls will be successful with the first call
691
691
  def self.do_geocode(address, options = {})
692
692
  geocode_ip = /^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})$/.match(address)
693
693
  provider_order = geocode_ip ? Geokit::Geocoders::ip_provider_order : Geokit::Geocoders::provider_order
694
-
694
+
695
695
  provider_order.each do |provider|
696
696
  begin
697
697
  klass = Geokit::Geocoders.const_get "#{Geokit::Inflector::camelize(provider.to_s)}Geocoder"
@@ -704,8 +704,8 @@ module Geokit
704
704
  # If we get here, we failed completely.
705
705
  GeoLoc.new
706
706
  end
707
-
708
- # This method will call one or more geocoders in the order specified in the
707
+
708
+ # This method will call one or more geocoders in the order specified in the
709
709
  # configuration until one of the geocoders work, only this time it's going
710
710
  # to try to reverse geocode a geographical point.
711
711
  def self.do_reverse_geocode(latlng)
@@ -721,6 +721,6 @@ module Geokit
721
721
  # If we get here, we failed completely.
722
722
  GeoLoc.new
723
723
  end
724
- end
724
+ end
725
725
  end
726
726
  end