geokit-premier 0.0.7 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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