Pr0d1r2-geokit 1.3.2.10 → 1.4.1

Sign up to get free protection for your applications and to get access to all the features.
data/Manifest.txt CHANGED
@@ -1,4 +1,3 @@
1
- .project
2
1
  History.txt
3
2
  Manifest.txt
4
3
  README.markdown
data/README.markdown CHANGED
@@ -124,12 +124,48 @@ creates a template with these settings and places it in `config/initializers/geo
124
124
  * Geonames - a free geocoder
125
125
 
126
126
  ### address geocoders that also provide reverse geocoding
127
- * Google Geocoder - requires an API key. Also supports multiple results.
127
+ * Google Geocoder - requires an API key. Also supports multiple results and bounding box/country code biasing.
128
128
 
129
129
  ### IP address geocoders
130
130
  * IP Geocoder - geocodes an IP address using hostip.info's web service.
131
131
  * Geoplugin.net -- another IP address geocoder
132
132
 
133
+ ### Google Geocoder Tricks
134
+
135
+ The Google Geocoder sports a number of useful tricks that elevate it a little bit above the rest of the currently supported geocoders. For starters, it returns a `suggested_bounds` property for all your geocoded results, so you can more easily decide where and how to center a map on the places you geocode. Here's a quick example:
136
+
137
+ irb> res = Geokit::Geocoders::GoogleGeocoder.geocode('140 Market St, San Francisco, CA')
138
+ irb> pp res.suggested_bounds
139
+ #<Geokit::Bounds:0x53b36c
140
+ @ne=#<Geokit::LatLng:0x53b204 @lat=37.7968528, @lng=-122.3926933>,
141
+ @sw=#<Geokit::LatLng:0x53b2b8 @lat=37.7905576, @lng=-122.3989885>>
142
+
143
+ In addition, you can use viewport or country code biasing to make sure the geocoders prefers results within a specific area. Say we wanted to geocode the city of Syracuse in Italy. A normal geocoding query would look like this:
144
+
145
+ irb> res = Geokit::Geocoder::GoogleGeocoder.geocode('Syracuse')
146
+ irb> res.full_address
147
+ => "Syracuse, NY, USA"
148
+
149
+ Not exactly what we were looking for. We know that Syracuse is in Italy, so we can tell the Google Geocoder to prefer results from Italy first, and then wander the Syracuses of the world. To do that, we have to pass Italy's ccTLD (country code top-level domain) to the `:bias` option of the `geocode` method. You can find a comprehensive list of all ccTLDs here: http://en.wikipedia.org/wiki/CcTLD.
150
+
151
+ irb> res = Geokit::Geocoder::GoogleGeocoder.geocode('Syracuse', :bias => 'it')
152
+ irb> res.full_address
153
+ => "Syracuse, Italy"
154
+
155
+ Alternatively, we can speficy the geocoding bias as a bounding box object. Say we wanted to geocode the Winnetka district in Los Angeles.
156
+
157
+ irb> res = Geokit::Geocoder::GoogleGeocoder.geocode('Winnetka')
158
+ irb> res.full_address
159
+ => "Winnetka, IL, USA"
160
+
161
+ Not it. What we can do is tell the geocoder to return results only from in and around LA.
162
+
163
+ irb> la_bounds = Geokit::Geocoder::GoogleGeocoder.geocode('Los Angeles').suggested_bounds
164
+ irb> res = Geokit::Geocoder::GoogleGeocoder.geocode('Winnetka', :bias => la_bounds)
165
+ irb> res.full_address
166
+ => "Winnetka, California, USA"
167
+
168
+
133
169
  ### The Multigeocoder
134
170
  Multi Geocoder - provides failover for the physical location geocoders, and also IP address geocoders. Its configured by setting Geokit::Geocoders::provider_order, and Geokit::Geocoders::ip_provider_order. You should call the Multi-Geocoder with its :geocode method, supplying one address parameter which is either a real street address, or an ip address. For example:
135
171
 
@@ -195,7 +231,7 @@ You must then also require such extenal file back in your main geokit configurat
195
231
  # and use :external to specify this geocoder in your list of geocoders.
196
232
  class ExternalGeocoder < Geocoder
197
233
  private
198
- def self.do_geocode(address)
234
+ def self.do_geocode(address, options = {})
199
235
  # Main geocoding method
200
236
  end
201
237
 
@@ -1,7 +1,7 @@
1
1
  class GeokitCachedGenerator < RspecModelGenerator
2
2
 
3
3
  def initialize(runtime_args, runtime_options = {})
4
- runtime_args = ['CachedLocation', 'address:string', 'provider:string', 'lng:float', 'lat:float', 'city:string']
4
+ runtime_args = ['CachedLocation', 'address:string', 'provider:string', 'lng:float', 'lat:float']
5
5
  super
6
6
  end
7
7
 
data/lib/geokit.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  module Geokit
2
- VERSION = '1.3.2.7'
2
+ VERSION = '1.4.1'
3
3
  # These defaults are used in Geokit::Mappable.distance_to and in acts_as_mappable
4
4
  @@default_units = :miles
5
5
  @@default_formula = :sphere
@@ -22,7 +22,7 @@ module Geokit
22
22
  end
23
23
 
24
24
  path = File.expand_path(File.dirname(__FILE__))
25
- $: << path unless $:.include?(path)
25
+ $:.unshift path unless $:.include?(path)
26
26
  require 'geokit/geocoders'
27
27
  require 'geokit/mappable'
28
28
  require 'geokit/cached'
@@ -22,7 +22,7 @@ module Geokit
22
22
 
23
23
  def geocode_address_cached
24
24
  @geo = multi_geocoder.geocode(complete_address)
25
- self.lat, self.lng, self.provider, self.city = @geo.lat, @geo.lng, @geo.provider, @geo.city if @geo.success
25
+ self.lat, self.lng, self.provider = @geo.lat, @geo.lng, @geo.provider if @geo.success
26
26
  end
27
27
 
28
28
  def cache_locations?
@@ -34,9 +34,9 @@ module Geokit
34
34
  end
35
35
 
36
36
  def cache_location!
37
- cached_location.cache!(:lat => lat, :lng => lng, :provider => provider, :city => city) if cache_locations?
37
+ cached_location.cache!(:lat => lat, :lng => lng, :provider => provider) if cache_locations?
38
38
  end
39
39
 
40
40
  end
41
41
  end
42
- end
42
+ end
@@ -14,13 +14,12 @@ module Geokit
14
14
 
15
15
  def cache!(attributes)
16
16
  self.attributes = attributes
17
- self.city = convert_to_utf8(self.city)
18
17
  save if new_record? || changed?
19
18
  end
20
19
 
21
20
  def update!
22
21
  if !by_google? && geo.success
23
- self.lat, self.lng, self.provider, self.city = geo.lat, geo.lng, geo.provider, convert_to_utf8(geo.city)
22
+ self.lat, self.lng, self.provider = geo.lat, geo.lng, geo.provider
24
23
  save if changed?
25
24
  end
26
25
  end
@@ -36,7 +35,7 @@ module Geokit
36
35
 
37
36
  def fake_geoloc
38
37
  geoloc = Geokit::GeoLoc.new
39
- geoloc.lat, geoloc.lng, geoloc.provider, geoloc.city, geoloc.success = lat, lng, provider, city, success?
38
+ geoloc.lat, geoloc.lng, geoloc.provider, geoloc.success = lat, lng, provider, success?
40
39
  geoloc
41
40
  end
42
41
 
@@ -45,7 +44,7 @@ module Geokit
45
44
  end
46
45
 
47
46
  def geoloc
48
- fake_geoloc
47
+ successful_geoloc || fake_geoloc
49
48
  end
50
49
 
51
50
  def by_google?
@@ -57,7 +56,7 @@ module Geokit
57
56
  end
58
57
 
59
58
  def changed?
60
- lat_changed? || lng_changed? || changed_to_google? || city_changed?
59
+ lat_changed? || lng_changed? || changed_to_google?
61
60
  end
62
61
 
63
62
  def geocoding_occured?
@@ -68,14 +67,6 @@ module Geokit
68
67
  !!(lat and lng)
69
68
  end
70
69
 
71
- def convert_to_utf8(str)
72
- begin
73
- Iconv.new('UTF-8', 'UTF-8').iconv(str)
74
- rescue Iconv::Failure => iconv_exception
75
- Iconv.new('UTF-8', 'ISO-8859-1').iconv(str)
76
- end
77
- end
78
-
79
70
  end
80
71
  end
81
72
  end
@@ -83,7 +83,7 @@ module Geokit
83
83
 
84
84
  def self.__define_accessors
85
85
  class_variables.each do |v|
86
- sym = v.delete("@").to_sym
86
+ sym = v.to_s.delete("@").to_sym
87
87
  unless self.respond_to? sym
88
88
  module_eval <<-EOS, __FILE__, __LINE__
89
89
  def self.#{sym}
@@ -121,8 +121,8 @@ module Geokit
121
121
  # Main method which calls the do_geocode template method which subclasses
122
122
  # are responsible for implementing. Returns a populated GeoLoc or an
123
123
  # empty one with a failed success code.
124
- def self.geocode(address)
125
- res = do_geocode(address)
124
+ def self.geocode(address, options = {})
125
+ res = do_geocode(address, options)
126
126
  return res.nil? ? GeoLoc.new : res
127
127
  end
128
128
  # Main method which calls the do_reverse_geocode template method which subclasses
@@ -174,8 +174,8 @@ module Geokit
174
174
  def self.inherited(clazz)
175
175
  class_name = clazz.name.split('::').last
176
176
  src = <<-END_SRC
177
- def self.#{Geokit::Inflector.underscore(class_name)}(address)
178
- #{class_name}.geocode(address)
177
+ def self.#{Geokit::Inflector.underscore(class_name)}(address, options = {})
178
+ #{class_name}.geocode(address, options)
179
179
  end
180
180
  END_SRC
181
181
  class_eval(src)
@@ -201,7 +201,7 @@ module Geokit
201
201
  private
202
202
 
203
203
  # Template method which does the geocode lookup.
204
- def self.do_geocode(address)
204
+ def self.do_geocode(address, options = {})
205
205
  raise ArgumentError('Geocoder.ca requires a GeoLoc argument') unless address.is_a?(GeoLoc)
206
206
  url = construct_request(address)
207
207
  res = self.call_geocoder_service(url)
@@ -243,7 +243,7 @@ module Geokit
243
243
  class UsGeocoder < Geocoder
244
244
 
245
245
  private
246
- def self.do_geocode(address)
246
+ def self.do_geocode(address, options = {})
247
247
  address_str = address.is_a?(GeoLoc) ? address.to_geocodeable_s : address
248
248
 
249
249
  query = (address_str =~ /^\d{5}(?:-\d{4})?$/ ? "zip" : "address") + "=#{Geokit::Inflector::url_escape(address_str)}"
@@ -291,7 +291,7 @@ module Geokit
291
291
  private
292
292
 
293
293
  # Template method which does the geocode lookup.
294
- def self.do_geocode(address)
294
+ def self.do_geocode(address, options = {})
295
295
  address_str = address.is_a?(GeoLoc) ? address.to_geocodeable_s : address
296
296
  url="http://api.local.yahoo.com/MapsService/V1/geocode?appid=#{Geokit::Geocoders::yahoo}&location=#{Geokit::Inflector::url_escape(address_str)}"
297
297
  res = self.call_geocoder_service(url)
@@ -337,7 +337,7 @@ module Geokit
337
337
  private
338
338
 
339
339
  # Template method which does the geocode lookup.
340
- def self.do_geocode(address)
340
+ def self.do_geocode(address, options = {})
341
341
  address_str = address.is_a?(GeoLoc) ? address.to_geocodeable_s : address
342
342
  # geonames need a space seperated search string
343
343
  address_str.gsub!(/,/, " ")
@@ -402,15 +402,50 @@ module Geokit
402
402
  end
403
403
 
404
404
  # Template method which does the geocode lookup.
405
- def self.do_geocode(address)
405
+ #
406
+ # Supports viewport/country code biasing
407
+ #
408
+ # ==== OPTIONS
409
+ # * :bias - This option makes the Google Geocoder return results biased to a particular
410
+ # country or viewport. Country code biasing is achieved by passing the ccTLD
411
+ # ('uk' for .co.uk, for example) as a :bias value. For a list of ccTLD's,
412
+ # look here: http://en.wikipedia.org/wiki/CcTLD. By default, the geocoder
413
+ # will be biased to results within the US (ccTLD .com).
414
+ #
415
+ # If you'd like the Google Geocoder to prefer results within a given viewport,
416
+ # you can pass a Geokit::Bounds object as the :bias value.
417
+ #
418
+ # ==== EXAMPLES
419
+ # # By default, the geocoder will return Syracuse, NY
420
+ # Geokit::Geocoders::GoogleGeocoder.geocode('Syracuse').country_code # => 'US'
421
+ # # With country code biasing, it returns Syracuse in Sicily, Italy
422
+ # Geokit::Geocoders::GoogleGeocoder.geocode('Syracuse', :bias => :it).country_code # => 'IT'
423
+ #
424
+ # # By default, the geocoder will return Winnetka, IL
425
+ # Geokit::Geocoders::GoogleGeocoder.geocode('Winnetka').state # => 'IL'
426
+ # # When biased to an bounding box around California, it will now return the Winnetka neighbourhood, CA
427
+ # bounds = Geokit::Bounds.normalize([34.074081, -118.694401], [34.321129, -118.399487])
428
+ # Geokit::Geocoders::GoogleGeocoder.geocode('Winnetka', :bias => bounds).state # => 'CA'
429
+ def self.do_geocode(address, options = {})
430
+ bias_str = options[:bias] ? construct_bias_string_from_options(options[:bias]) : ''
406
431
  address_str = address.is_a?(GeoLoc) ? address.to_geocodeable_s : address
407
- res = self.call_geocoder_service("http://maps.google.com/maps/geo?q=#{Geokit::Inflector::url_escape(address_str)}&output=xml&key=#{Geokit::Geocoders::google}&oe=utf-8")
432
+ res = self.call_geocoder_service("http://maps.google.com/maps/geo?q=#{Geokit::Inflector::url_escape(address_str)}&output=xml#{bias_str}&key=#{Geokit::Geocoders::google}&oe=utf-8")
408
433
  return GeoLoc.new if !res.is_a?(Net::HTTPSuccess)
409
434
  xml = res.body
410
435
  logger.debug "Google geocoding. Address: #{address}. Result: #{xml}"
411
436
  return self.xml2GeoLoc(xml, address)
412
437
  end
413
438
 
439
+ def self.construct_bias_string_from_options(bias)
440
+ if bias.is_a?(String) or bias.is_a?(Symbol)
441
+ # country code biasing
442
+ "&gl=#{bias.to_s.downcase}"
443
+ elsif bias.is_a?(Bounds)
444
+ # viewport biasing
445
+ "&ll=#{bias.center.ll}&spn=#{bias.to_span.ll}"
446
+ end
447
+ end
448
+
414
449
  def self.xml2GeoLoc(xml, address="")
415
450
  doc=REXML::Document.new(xml)
416
451
 
@@ -462,6 +497,14 @@ module Geokit
462
497
  address_details=doc.elements['.//*[local-name() = "AddressDetails"]']
463
498
  res.accuracy = address_details ? address_details.attributes['Accuracy'].to_i : 0
464
499
  res.precision=%w{unknown country state state city zip zip+4 street address building}[res.accuracy]
500
+
501
+ # google returns a set of suggested boundaries for the geocoded result
502
+ if suggested_bounds = doc.elements['//LatLonBox']
503
+ res.suggested_bounds = Bounds.normalize(
504
+ [suggested_bounds.attributes['south'], suggested_bounds.attributes['west']],
505
+ [suggested_bounds.attributes['north'], suggested_bounds.attributes['east']])
506
+ end
507
+
465
508
  res.success=true
466
509
 
467
510
  return res
@@ -477,7 +520,7 @@ module Geokit
477
520
  class GeoPluginGeocoder < Geocoder
478
521
  private
479
522
 
480
- def self.do_geocode(ip)
523
+ def self.do_geocode(ip, options = {})
481
524
  return GeoLoc.new unless /^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})?$/.match(ip)
482
525
  response = self.call_geocoder_service("http://www.geoplugin.net/xml.gp?ip=#{ip}")
483
526
  return response.is_a?(Net::HTTPSuccess) ? parse_xml(response.body) : GeoLoc.new
@@ -510,7 +553,7 @@ module Geokit
510
553
  # Given an IP address, returns a GeoLoc instance which contains latitude,
511
554
  # longitude, city, and country code. Sets the success attribute to false if the ip
512
555
  # parameter does not match an ip address.
513
- def self.do_geocode(ip)
556
+ def self.do_geocode(ip, options = {})
514
557
  return GeoLoc.new if '0.0.0.0' == ip
515
558
  return GeoLoc.new unless /^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})?$/.match(ip)
516
559
  url = "http://api.hostip.info/get_html.php?ip=#{ip}&position=true"
@@ -565,14 +608,14 @@ module Geokit
565
608
  #
566
609
  # The failover approach is crucial for production-grade apps, but is rarely used.
567
610
  # 98% of your geocoding calls will be successful with the first call
568
- def self.do_geocode(address)
611
+ def self.do_geocode(address, options = {})
569
612
  geocode_ip = /^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})$/.match(address)
570
613
  provider_order = geocode_ip ? Geokit::Geocoders::ip_provider_order : Geokit::Geocoders::provider_order
571
614
 
572
615
  provider_order.each do |provider|
573
616
  begin
574
617
  klass = Geokit::Geocoders.const_get "#{Geokit::Inflector::camelize(provider.to_s)}Geocoder"
575
- res = klass.send :geocode, address
618
+ res = klass.send :geocode, address, options
576
619
  return res if res.success?
577
620
  rescue
578
621
  logger.error("Something has gone very wrong during geocoding, OR you have configured an invalid class name in Geokit::Geocoders::provider_order. Address: #{address}. Provider: #{provider}")
@@ -581,6 +624,23 @@ module Geokit
581
624
  # If we get here, we failed completely.
582
625
  GeoLoc.new
583
626
  end
627
+
628
+ # This method will call one or more geocoders in the order specified in the
629
+ # configuration until one of the geocoders work, only this time it's going
630
+ # to try to reverse geocode a geographical point.
631
+ def self.do_reverse_geocode(latlng)
632
+ Geokit::Geocoders::provider_order.each do |provider|
633
+ begin
634
+ klass = Geokit::Geocoders.const_get "#{Geokit::Inflector::camelize(provider.to_s)}Geocoder"
635
+ res = klass.send :reverse_geocode, latlng
636
+ return res if res.success?
637
+ rescue
638
+ logger.error("Something has gone very wrong during reverse geocoding, OR you have configured an invalid class name in Geokit::Geocoders::provider_order. LatLng: #{latlng}. Provider: #{provider}")
639
+ end
640
+ end
641
+ # If we get here, we failed completely.
642
+ GeoLoc.new
643
+ end
584
644
  end
585
645
  end
586
646
  end
@@ -110,8 +110,8 @@ module Geokit
110
110
  end
111
111
 
112
112
  # Geocodes a location using the multi geocoder.
113
- def geocode(location)
114
- res = Geocoders::MultiGeocoder.geocode(location)
113
+ def geocode(location, options = {})
114
+ res = Geocoders::MultiGeocoder.geocode(location, options)
115
115
  return res if res.success?
116
116
  raise Geokit::Geocoders::GeocodeError
117
117
  end
@@ -292,6 +292,30 @@ module Geokit
292
292
  raise ArgumentError.new("#{thing} (#{thing.class}) cannot be normalized to a LatLng. We tried interpreting it as an array, string, Mappable, etc., but no dice.")
293
293
  end
294
294
 
295
+ # Reverse geocodes a LatLng object using the MultiGeocoder (default), or optionally
296
+ # using a geocoder of your choosing. Returns a new Geokit::GeoLoc object
297
+ #
298
+ # ==== Options
299
+ # * :using - Specifies the geocoder to use for reverse geocoding. Defaults to
300
+ # MultiGeocoder. Can be either the geocoder class (or any class that
301
+ # implements do_reverse_geocode for that matter), or the name of
302
+ # the class without the "Geocoder" part (e.g. :google)
303
+ #
304
+ # ==== Examples
305
+ # LatLng.new(51.4578329, 7.0166848).reverse_geocode # => #<Geokit::GeoLoc:0x12dac20 @state...>
306
+ # LatLng.new(51.4578329, 7.0166848).reverse_geocode(:using => :google) # => #<Geokit::GeoLoc:0x12dac20 @state...>
307
+ # LatLng.new(51.4578329, 7.0166848).reverse_geocode(:using => Geokit::Geocoders::GoogleGeocoder) # => #<Geokit::GeoLoc:0x12dac20 @state...>
308
+ def reverse_geocode(options = { :using => Geokit::Geocoders::MultiGeocoder })
309
+ if options[:using].is_a?(String) or options[:using].is_a?(Symbol)
310
+ provider = Geokit::Geocoders.const_get("#{Geokit::Inflector::camelize(options[:using].to_s)}Geocoder")
311
+ elsif options[:using].respond_to?(:do_reverse_geocode)
312
+ provider = options[:using]
313
+ else
314
+ raise ArgumentError.new("#{options[:using]} is not a valid geocoder.")
315
+ end
316
+
317
+ provider.send(:reverse_geocode, self)
318
+ end
295
319
  end
296
320
 
297
321
  # This class encapsulates the result of a geocoding call.
@@ -322,7 +346,7 @@ module Geokit
322
346
  # Attributes set upon return from geocoding. Success will be true for successful
323
347
  # geocode lookups. The provider will be set to the name of the providing geocoder.
324
348
  # Finally, precision is an indicator of the accuracy of the geocoding.
325
- attr_accessor :success, :provider, :precision
349
+ attr_accessor :success, :provider, :precision, :suggested_bounds
326
350
  # Street number and street name are extracted from the street address attribute.
327
351
  attr_reader :street_number, :street_name
328
352
  # accuracy is set for Yahoo and Google geocoders, it is a numeric value of the
@@ -387,8 +411,8 @@ module Geokit
387
411
  # Sets the street address after capitalizing each word within the street address.
388
412
  def street_address=(address)
389
413
  @street_address = Geokit::Inflector::titleize(address) if address
390
- end
391
-
414
+ end
415
+
392
416
  # Returns a comma-delimited string consisting of the street address, city, state,
393
417
  # zip, and country code. Only includes those attributes that are non-blank.
394
418
  def to_geocodeable_s
@@ -457,6 +481,16 @@ module Geokit
457
481
  other.is_a?(Bounds) ? self.sw == other.sw && self.ne == other.ne : false
458
482
  end
459
483
 
484
+ # Equivalent to Google Maps API's .toSpan() method on GLatLng's.
485
+ #
486
+ # Returns a LatLng object, whose coordinates represent the size of a rectangle
487
+ # defined by these bounds.
488
+ def to_span
489
+ lat_span = (@ne.lat - @sw.lat).abs
490
+ lng_span = (crosses_meridian? ? 360 + @ne.lng - @sw.lng : @ne.lng - @sw.lng).abs
491
+ Geokit::LatLng.new(lat_span, lng_span)
492
+ end
493
+
460
494
  class <<self
461
495
 
462
496
  # returns an instance of bounds which completely encompases the given circle
@@ -29,7 +29,8 @@ class BaseGeocoderTest < Test::Unit::TestCase #:nodoc: all
29
29
  @full_address = '100 Spear St, San Francisco, CA, 94105-1522, US'
30
30
  @full_address_short_zip = '100 Spear St, San Francisco, CA, 94105, US'
31
31
 
32
- @success = Geokit::GeoLoc.new({:city=>"SAN FRANCISCO", :state=>"CA", :country_code=>"US", :lat=>37.7742, :lng=>-122.417068})
32
+ @latlng = Geokit::LatLng.new(37.7742, -122.417068)
33
+ @success = Geokit::GeoLoc.new({:city=>"SAN FRANCISCO", :state=>"CA", :country_code=>"US", :lat=>@latlng.lat, :lng=>@latlng.lng})
33
34
  @success.success = true
34
35
  end
35
36
 
data/test/test_bounds.rb CHANGED
@@ -71,4 +71,27 @@ class BoundsTest < Test::Unit::TestCase #:nodoc: all
71
71
  assert !bounds.contains?(outside)
72
72
  end
73
73
 
74
+ def test_bounds_to_span
75
+ sw = Geokit::LatLng.new(32, -96)
76
+ ne = Geokit::LatLng.new(40, -70)
77
+ bounds = Geokit::Bounds.new(sw, ne)
78
+
79
+ assert_equal Geokit::LatLng.new(8, 26), bounds.to_span
80
+ end
81
+
82
+ def test_bounds_to_span_with_bounds_crossing_prime_meridian
83
+ sw = Geokit::LatLng.new(20, -70)
84
+ ne = Geokit::LatLng.new(40, 100)
85
+ bounds = Geokit::Bounds.new(sw, ne)
86
+
87
+ assert_equal Geokit::LatLng.new(20, 170), bounds.to_span
88
+ end
89
+
90
+ def test_bounds_to_span_with_bounds_crossing_dateline
91
+ sw = Geokit::LatLng.new(20, 100)
92
+ ne = Geokit::LatLng.new(40, -70)
93
+ bounds = Geokit::Bounds.new(sw, ne)
94
+
95
+ assert_equal Geokit::LatLng.new(20, 190), bounds.to_span
96
+ end
74
97
  end
@@ -7,6 +7,10 @@ class GoogleGeocoderTest < BaseGeocoderTest #:nodoc: all
7
7
  GOOGLE_FULL=<<-EOF.strip
8
8
  <?xml version="1.0" encoding="UTF-8"?><kml xmlns="http://earth.google.com/kml/2.0"><Response><name>100 spear st, san francisco, ca</name><Status><code>200</code><request>geocode</request></Status><Placemark><address>100 Spear St, San Francisco, CA 94105, USA</address><AddressDetails Accuracy="8" xmlns="urn:oasis:names:tc:ciq:xsdschema:xAL:2.0"><Country><CountryNameCode>US</CountryNameCode><AdministrativeArea><AdministrativeAreaName>CA</AdministrativeAreaName><SubAdministrativeArea><SubAdministrativeAreaName>San Francisco</SubAdministrativeAreaName><Locality><LocalityName>San Francisco</LocalityName><Thoroughfare><ThoroughfareName>100 Spear St</ThoroughfareName></Thoroughfare><PostalCode><PostalCodeNumber>94105</PostalCodeNumber></PostalCode></Locality></SubAdministrativeArea></AdministrativeArea></Country></AddressDetails><Point><coordinates>-122.393985,37.792501,0</coordinates></Point></Placemark></Response></kml>
9
9
  EOF
10
+
11
+ GOOGLE_RESULT_WITH_SUGGESTED_BOUNDS=<<-EOF.strip
12
+ <?xml version="1.0" encoding="UTF-8"?><kml xmlns="http://earth.google.com/kml/2.0"><Response><name>100 spear st, san francisco, ca</name><Status><code>200</code><request>geocode</request></Status><Placemark><address>100 Spear St, San Francisco, CA 94105, USA</address><AddressDetails Accuracy="8" xmlns="urn:oasis:names:tc:ciq:xsdschema:xAL:2.0"><Country><CountryNameCode>US</CountryNameCode><AdministrativeArea><AdministrativeAreaName>CA</AdministrativeAreaName><SubAdministrativeArea><SubAdministrativeAreaName>San Francisco</SubAdministrativeAreaName><Locality><LocalityName>San Francisco</LocalityName><Thoroughfare><ThoroughfareName>100 Spear St</ThoroughfareName></Thoroughfare><PostalCode><PostalCodeNumber>94105</PostalCodeNumber></PostalCode></Locality></SubAdministrativeArea></AdministrativeArea></Country></AddressDetails><ExtendedData><LatLonBox north="37.7956328" south="37.7893376" east="-122.3908573" west="-122.3971525" /></ExtendedData><Point><coordinates>-122.393985,37.792501,0</coordinates></Point></Placemark></Response></kml>
13
+ EOF
10
14
 
11
15
  GOOGLE_CITY=<<-EOF.strip
12
16
  <?xml version="1.0" encoding="UTF-8"?><kml xmlns="http://earth.google.com/kml/2.0"><Response><name>San Francisco</name><Status><code>200</code><request>geocode</request></Status><Placemark><address>San Francisco, CA, USA</address><AddressDetails Accuracy="4" xmlns="urn:oasis:names:tc:ciq:xsdschema:xAL:2.0"><Country><CountryNameCode>US</CountryNameCode><AdministrativeArea><AdministrativeAreaName>CA</AdministrativeAreaName><Locality><LocalityName>San Francisco</LocalityName></Locality></AdministrativeArea></Country></AddressDetails><Point><coordinates>-122.418333,37.775000,0</coordinates></Point></Placemark></Response></kml>
@@ -14,6 +18,14 @@ class GoogleGeocoderTest < BaseGeocoderTest #:nodoc: all
14
18
 
15
19
  GOOGLE_MULTI="<?xml version='1.0' encoding='UTF-8'?>\n<kml xmlns='http://earth.google.com/kml/2.0'><Response>\n <name>via Sandro Pertini 8, Ossona, MI</name>\n <Status>\n <code>200</code>\n <request>geocode</request>\n </Status>\n <Placemark id='p1'>\n <address>Via Sandro Pertini, 8, 20010 Mesero MI, Italy</address>\n <AddressDetails Accuracy='8' xmlns='urn:oasis:names:tc:ciq:xsdschema:xAL:2.0'><Country><CountryNameCode>IT</CountryNameCode><CountryName>Italy</CountryName><AdministrativeArea><AdministrativeAreaName>Lombardy</AdministrativeAreaName><SubAdministrativeArea><SubAdministrativeAreaName>Milan</SubAdministrativeAreaName><Locality><LocalityName>Mesero</LocalityName><Thoroughfare><ThoroughfareName>8 Via Sandro Pertini</ThoroughfareName></Thoroughfare><PostalCode><PostalCodeNumber>20010</PostalCodeNumber></PostalCode></Locality></SubAdministrativeArea></AdministrativeArea></Country></AddressDetails>\n <Point><coordinates>8.8527131,45.4966243,0</coordinates></Point>\n </Placemark>\n <Placemark id='p2'>\n <address>Via Sandro Pertini, 20010 Ossona MI, Italy</address>\n <AddressDetails Accuracy='6' xmlns='urn:oasis:names:tc:ciq:xsdschema:xAL:2.0'><Country><CountryNameCode>IT</CountryNameCode><CountryName>Italy</CountryName><AdministrativeArea><AdministrativeAreaName>Lombardy</AdministrativeAreaName><SubAdministrativeArea><SubAdministrativeAreaName>Milan</SubAdministrativeAreaName><Locality><LocalityName>Ossona</LocalityName><Thoroughfare><ThoroughfareName>Via Sandro Pertini</ThoroughfareName></Thoroughfare><PostalCode><PostalCodeNumber>20010</PostalCodeNumber></PostalCode></Locality></SubAdministrativeArea></AdministrativeArea></Country></AddressDetails>\n <Point><coordinates>8.9023200,45.5074444,0</coordinates></Point>\n </Placemark>\n</Response></kml>\n"
16
20
 
21
+ GOOGLE_COUNTRY_CODE_BIASED_RESULT = <<-EOF.strip
22
+ <?xml version="1.0" encoding="UTF-8" ?><kml xmlns="http://earth.google.com/kml/2.0"><Response><name>Syracuse</name><Status><code>200</code><request>geocode</request></Status><Placemark id="p1"><address>Syracuse, Italy</address><AddressDetails Accuracy="3" xmlns="urn:oasis:names:tc:ciq:xsdschema:xAL:2.0"><Country><CountryNameCode>IT</CountryNameCode><CountryName>Italy</CountryName><AdministrativeArea><AdministrativeAreaName>Sicily</AdministrativeAreaName><SubAdministrativeArea><SubAdministrativeAreaName>Syracuse</SubAdministrativeAreaName></SubAdministrativeArea></AdministrativeArea></Country></AddressDetails><ExtendedData><LatLonBox north="37.4125978" south="36.6441736" east="15.3367367" west="14.7724913" /></ExtendedData><Point><coordinates>14.9856176,37.0630218,0</coordinates></Point></Placemark></Response></kml>
23
+ EOF
24
+
25
+ GOOGLE_BOUNDS_BIASED_RESULT = <<-EOF.strip
26
+ <?xml version="1.0" encoding="UTF-8" ?><kml xmlns="http://earth.google.com/kml/2.0"><Response><name>Winnetka</name><Status><code>200</code><request>geocode</request></Status><Placemark id="p1"><address>Winnetka, California, USA</address><AddressDetails Accuracy="4" xmlns="urn:oasis:names:tc:ciq:xsdschema:xAL:2.0"><Country><CountryNameCode>US</CountryNameCode><CountryName>USA</CountryName><AdministrativeArea><AdministrativeAreaName>CA</AdministrativeAreaName><AddressLine>Winnetka</AddressLine></AdministrativeArea></Country></AddressDetails><ExtendedData><LatLonBox north="34.2353090" south="34.1791050" east="-118.5534191" west="-118.5883200" /></ExtendedData><Point><coordinates>-118.5710220,34.2131710,0</coordinates></Point></Placemark></Response></kml>
27
+ EOF
28
+
17
29
  def setup
18
30
  super
19
31
  @google_full_hash = {:street_address=>"100 Spear St", :city=>"San Francisco", :state=>"CA", :zip=>"94105", :country_code=>"US"}
@@ -99,6 +111,17 @@ class GoogleGeocoderTest < BaseGeocoderTest #:nodoc: all
99
111
  assert_equal "google", res.provider
100
112
  end
101
113
 
114
+ def test_google_suggested_bounds
115
+ response = MockSuccess.new
116
+ response.expects(:body).returns(GOOGLE_RESULT_WITH_SUGGESTED_BOUNDS)
117
+ url = "http://maps.google.com/maps/geo?q=#{Geokit::Inflector.url_escape(@full_address_short_zip)}&output=xml&key=Google&oe=utf-8"
118
+ Geokit::Geocoders::GoogleGeocoder.expects(:call_geocoder_service).with(url).returns(response)
119
+ res = Geokit::Geocoders::GoogleGeocoder.geocode(@google_full_loc)
120
+
121
+ assert_instance_of Geokit::Bounds, res.suggested_bounds
122
+ assert_equal Geokit::Bounds.new(Geokit::LatLng.new(37.7893376, -122.3971525), Geokit::LatLng.new(37.7956328, -122.3908573)), res.suggested_bounds
123
+ end
124
+
102
125
  def test_service_unavailable
103
126
  response = MockFailure.new
104
127
  url = "http://maps.google.com/maps/geo?q=#{Geokit::Inflector.url_escape(@address)}&output=xml&key=Google&oe=utf-8"
@@ -131,4 +154,30 @@ class GoogleGeocoderTest < BaseGeocoderTest #:nodoc: all
131
154
  assert_equal "Via Sandro Pertini", res.street_address
132
155
  assert_equal "google", res.provider
133
156
  end
157
+
158
+ def test_country_code_biasing
159
+ response = MockSuccess.new
160
+ response.expects(:body).returns(GOOGLE_COUNTRY_CODE_BIASED_RESULT)
161
+
162
+ url = "http://maps.google.com/maps/geo?q=Syracuse&output=xml&gl=it&key=Google&oe=utf-8"
163
+ Geokit::Geocoders::GoogleGeocoder.expects(:call_geocoder_service).with(url).returns(response)
164
+ biased_result = Geokit::Geocoders::GoogleGeocoder.geocode('Syracuse', :bias => 'it')
165
+
166
+ assert_equal 'IT', biased_result.country_code
167
+ assert_equal 'Sicily', biased_result.state
168
+ end
169
+
170
+ def test_bounds_biasing
171
+ response = MockSuccess.new
172
+ response.expects(:body).returns(GOOGLE_BOUNDS_BIASED_RESULT)
173
+
174
+ url = "http://maps.google.com/maps/geo?q=Winnetka&output=xml&ll=34.197693208849,-118.547160027785&spn=0.247047999999999,0.294914000000006&key=Google&oe=utf-8"
175
+ Geokit::Geocoders::GoogleGeocoder.expects(:call_geocoder_service).with(url).returns(response)
176
+
177
+ bounds = Geokit::Bounds.normalize([34.074081, -118.694401], [34.321129, -118.399487])
178
+ biased_result = Geokit::Geocoders::GoogleGeocoder.geocode('Winnetka', :bias => bounds)
179
+
180
+ assert_equal 'US', biased_result.country_code
181
+ assert_equal 'CA', biased_result.state
182
+ end
134
183
  end
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  require 'test/unit'
2
4
  require 'lib/geokit'
3
5
 
data/test/test_latlng.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require 'test/unit'
2
2
  require 'lib/geokit'
3
+ require 'mocha'
3
4
 
4
5
  class LatLngTest < Test::Unit::TestCase #:nodoc: all
5
6
 
@@ -9,6 +10,25 @@ class LatLngTest < Test::Unit::TestCase #:nodoc: all
9
10
  @point = Geokit::LatLng.new(@loc_a.lat, @loc_a.lng)
10
11
  end
11
12
 
13
+ def valid_reverse_geocoding_result
14
+ location = Geokit::GeoLoc.new({
15
+ :city => "Essen",
16
+ :country_code => "DE",
17
+ :lat => 51.4578329,
18
+ :lng => 7.0166848,
19
+ :provider => "google",
20
+ :state => "Nordrhein-Westfalen",
21
+ :street_address => "Porscheplatz 1",
22
+ :zip => "45127"
23
+ })
24
+
25
+ location.full_address = "Porscheplatz 1, 45127 Essen, Deutschland"
26
+ location.precision = 'address'
27
+ location.provider = 'google'
28
+ location.success = true
29
+ location
30
+ end
31
+
12
32
  def test_distance_between_same_using_defaults
13
33
  assert_equal 0, Geokit::LatLng.distance_between(@loc_a, @loc_a)
14
34
  assert_equal 0, @loc_a.distance_to(@loc_a)
@@ -145,4 +165,45 @@ class LatLngTest < Test::Unit::TestCase #:nodoc: all
145
165
  assert first.eql?(second)
146
166
  assert second.eql?(first)
147
167
  end
168
+
169
+ def test_reverse_geocode
170
+ point = Geokit::LatLng.new(51.4578329, 7.0166848)
171
+ Geokit::Geocoders::MultiGeocoder.expects(:reverse_geocode).with(point).returns(valid_reverse_geocoding_result)
172
+ res = point.reverse_geocode
173
+
174
+ assert_equal "Nordrhein-Westfalen", res.state
175
+ assert_equal "Essen", res.city
176
+ assert_equal "45127", res.zip
177
+ assert_equal "51.4578329,7.0166848", res.ll # slightly dif from yahoo
178
+ assert res.is_us? == false
179
+ assert_equal "Porscheplatz 1, 45127 Essen, Deutschland", res.full_address #slightly different from yahoo
180
+ end
181
+
182
+ def test_reverse_geocoding_using_specific_geocoder
183
+ point = Geokit::LatLng.new(51.4578329, 7.0166848)
184
+ Geokit::Geocoders::GoogleGeocoder.expects(:reverse_geocode).with(point).returns(valid_reverse_geocoding_result)
185
+ res = point.reverse_geocode(:using => Geokit::Geocoders::GoogleGeocoder)
186
+
187
+ assert_equal "Nordrhein-Westfalen", res.state
188
+ assert_equal "Essen", res.city
189
+ assert_equal "45127", res.zip
190
+ assert_equal "51.4578329,7.0166848", res.ll # slightly dif from yahoo
191
+ assert res.is_us? == false
192
+ assert_equal "Porscheplatz 1, 45127 Essen, Deutschland", res.full_address #slightly different from yahoo
193
+ assert_equal "google", res.provider
194
+ end
195
+
196
+ def test_reverse_geocoding_using_specific_geocoder_short_syntax
197
+ point = Geokit::LatLng.new(51.4578329, 7.0166848)
198
+ Geokit::Geocoders::GoogleGeocoder.expects(:reverse_geocode).with(point).returns(valid_reverse_geocoding_result)
199
+ res = point.reverse_geocode(:using => :google)
200
+
201
+ assert_equal "Nordrhein-Westfalen", res.state
202
+ assert_equal "Essen", res.city
203
+ assert_equal "45127", res.zip
204
+ assert_equal "51.4578329,7.0166848", res.ll # slightly dif from yahoo
205
+ assert res.is_us? == false
206
+ assert_equal "Porscheplatz 1, 45127 Essen, Deutschland", res.full_address #slightly different from yahoo
207
+ assert_equal "google", res.provider
208
+ end
148
209
  end
@@ -10,27 +10,27 @@ class MultiGeocoderTest < BaseGeocoderTest #:nodoc: all
10
10
  end
11
11
 
12
12
  def test_successful_first
13
- Geokit::Geocoders::GoogleGeocoder.expects(:geocode).with(@address).returns(@success)
13
+ Geokit::Geocoders::GoogleGeocoder.expects(:geocode).with(@address, {}).returns(@success)
14
14
  assert_equal @success, Geokit::Geocoders::MultiGeocoder.geocode(@address)
15
15
  end
16
16
 
17
17
  def test_failover
18
- Geokit::Geocoders::GoogleGeocoder.expects(:geocode).with(@address).returns(@failure)
19
- Geokit::Geocoders::YahooGeocoder.expects(:geocode).with(@address).returns(@success)
18
+ Geokit::Geocoders::GoogleGeocoder.expects(:geocode).with(@address, {}).returns(@failure)
19
+ Geokit::Geocoders::YahooGeocoder.expects(:geocode).with(@address, {}).returns(@success)
20
20
  assert_equal @success, Geokit::Geocoders::MultiGeocoder.geocode(@address)
21
21
  end
22
22
 
23
23
  def test_double_failover
24
- Geokit::Geocoders::GoogleGeocoder.expects(:geocode).with(@address).returns(@failure)
25
- Geokit::Geocoders::YahooGeocoder.expects(:geocode).with(@address).returns(@failure)
26
- Geokit::Geocoders::UsGeocoder.expects(:geocode).with(@address).returns(@success)
24
+ Geokit::Geocoders::GoogleGeocoder.expects(:geocode).with(@address, {}).returns(@failure)
25
+ Geokit::Geocoders::YahooGeocoder.expects(:geocode).with(@address, {}).returns(@failure)
26
+ Geokit::Geocoders::UsGeocoder.expects(:geocode).with(@address, {}).returns(@success)
27
27
  assert_equal @success, Geokit::Geocoders::MultiGeocoder.geocode(@address)
28
28
  end
29
29
 
30
30
  def test_failure
31
- Geokit::Geocoders::GoogleGeocoder.expects(:geocode).with(@address).returns(@failure)
32
- Geokit::Geocoders::YahooGeocoder.expects(:geocode).with(@address).returns(@failure)
33
- Geokit::Geocoders::UsGeocoder.expects(:geocode).with(@address).returns(@failure)
31
+ Geokit::Geocoders::GoogleGeocoder.expects(:geocode).with(@address, {}).returns(@failure)
32
+ Geokit::Geocoders::YahooGeocoder.expects(:geocode).with(@address, {}).returns(@failure)
33
+ Geokit::Geocoders::UsGeocoder.expects(:geocode).with(@address, {}).returns(@failure)
34
34
  assert_equal @failure, Geokit::Geocoders::MultiGeocoder.geocode(@address)
35
35
  end
36
36
 
@@ -45,10 +45,49 @@ class MultiGeocoderTest < BaseGeocoderTest #:nodoc: all
45
45
  t1, t2 = Geokit::Geocoders.provider_order, Geokit::Geocoders.ip_provider_order # will need to reset after
46
46
  Geokit::Geocoders.provider_order = [:google]
47
47
  Geokit::Geocoders.ip_provider_order = [:geo_plugin]
48
- Geokit::Geocoders::GoogleGeocoder.expects(:geocode).with("").returns(@failure)
48
+ Geokit::Geocoders::GoogleGeocoder.expects(:geocode).with("", {}).returns(@failure)
49
49
  Geokit::Geocoders::GeoPluginGeocoder.expects(:geocode).never
50
50
  assert_equal @failure, Geokit::Geocoders::MultiGeocoder.geocode("")
51
51
  Geokit::Geocoders.provider_order, Geokit::Geocoders.ip_provider_order = t1, t2 # reset to orig values
52
52
  end
53
53
 
54
+ def test_reverse_geocode_successful_first
55
+ Geokit::Geocoders::GoogleGeocoder.expects(:reverse_geocode).with(@latlng).returns(@success)
56
+ assert_equal @success, Geokit::Geocoders::MultiGeocoder.reverse_geocode(@latlng)
57
+ end
58
+
59
+ def test_reverse_geocode_failover
60
+ Geokit::Geocoders::GoogleGeocoder.expects(:reverse_geocode).with(@latlng).returns(@failure)
61
+ Geokit::Geocoders::YahooGeocoder.expects(:reverse_geocode).with(@latlng).returns(@success)
62
+ assert_equal @success, Geokit::Geocoders::MultiGeocoder.reverse_geocode(@latlng)
63
+ end
64
+
65
+ def test_reverse_geocode_double_failover
66
+ Geokit::Geocoders::GoogleGeocoder.expects(:reverse_geocode).with(@latlng).returns(@failure)
67
+ Geokit::Geocoders::YahooGeocoder.expects(:reverse_geocode).with(@latlng).returns(@failure)
68
+ Geokit::Geocoders::UsGeocoder.expects(:reverse_geocode).with(@latlng).returns(@success)
69
+ assert_equal @success, Geokit::Geocoders::MultiGeocoder.reverse_geocode(@latlng)
70
+ end
71
+
72
+ def test_reverse_geocode_failure
73
+ Geokit::Geocoders::GoogleGeocoder.expects(:reverse_geocode).with(@latlng).returns(@failure)
74
+ Geokit::Geocoders::YahooGeocoder.expects(:reverse_geocode).with(@latlng).returns(@failure)
75
+ Geokit::Geocoders::UsGeocoder.expects(:reverse_geocode).with(@latlng).returns(@failure)
76
+ assert_equal @failure, Geokit::Geocoders::MultiGeocoder.reverse_geocode(@latlng)
77
+ end
78
+
79
+ def test_reverse_geocode_with_invalid_provider
80
+ temp = Geokit::Geocoders::provider_order
81
+ Geokit::Geocoders.provider_order = [:bogus]
82
+ assert_equal @failure, Geokit::Geocoders::MultiGeocoder.reverse_geocode(@latlng)
83
+ Geokit::Geocoders.provider_order = temp
84
+ end
85
+
86
+ def test_reverse_geocode_with_blank_latlng
87
+ t1 = Geokit::Geocoders.provider_order # will need to reset after
88
+ Geokit::Geocoders.provider_order = [:google]
89
+ Geokit::Geocoders::GoogleGeocoder.expects(:reverse_geocode).with("").returns(@failure)
90
+ assert_equal @failure, Geokit::Geocoders::MultiGeocoder.reverse_geocode("")
91
+ Geokit::Geocoders.provider_order = t1 # reset to orig values
92
+ end
54
93
  end
@@ -12,19 +12,19 @@ class MultiIpGeocoderTest < BaseGeocoderTest #:nodoc: all
12
12
  end
13
13
 
14
14
  def test_successful_first
15
- Geokit::Geocoders::GeoPluginGeocoder.expects(:geocode).with(@ip_address).returns(@success)
15
+ Geokit::Geocoders::GeoPluginGeocoder.expects(:geocode).with(@ip_address, {}).returns(@success)
16
16
  assert_equal @success, Geokit::Geocoders::MultiGeocoder.geocode(@ip_address)
17
17
  end
18
18
 
19
19
  def test_failover
20
- Geokit::Geocoders::GeoPluginGeocoder.expects(:geocode).with(@ip_address).returns(@failure)
21
- Geokit::Geocoders::IpGeocoder.expects(:geocode).with(@ip_address).returns(@success)
20
+ Geokit::Geocoders::GeoPluginGeocoder.expects(:geocode).with(@ip_address, {}).returns(@failure)
21
+ Geokit::Geocoders::IpGeocoder.expects(:geocode).with(@ip_address, {}).returns(@success)
22
22
  assert_equal @success, Geokit::Geocoders::MultiGeocoder.geocode(@ip_address)
23
23
  end
24
24
 
25
25
  def test_failure
26
- Geokit::Geocoders::GeoPluginGeocoder.expects(:geocode).with(@ip_address).returns(@failure)
27
- Geokit::Geocoders::IpGeocoder.expects(:geocode).with(@ip_address).returns(@failure)
26
+ Geokit::Geocoders::GeoPluginGeocoder.expects(:geocode).with(@ip_address, {}).returns(@failure)
27
+ Geokit::Geocoders::IpGeocoder.expects(:geocode).with(@ip_address, {}).returns(@failure)
28
28
  assert_equal @failure, Geokit::Geocoders::MultiGeocoder.geocode(@ip_address)
29
29
  end
30
30
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: Pr0d1r2-geokit
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.2.10
4
+ version: 1.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andre Lewis and Bill Eisenhauer and Pr0d1r2 (Marcin Nowicki)
@@ -9,11 +9,11 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-11-30 00:00:00 +01:00
12
+ date: 2009-06-17 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
16
- description: Geokit Gem modified to have support for caching
16
+ description: Geokit Gem
17
17
  email:
18
18
  - andre@earthcode.com / bill_eisenhauer@yahoo.com / pr0d1r2@gmail.com
19
19
  executables: []
@@ -48,8 +48,6 @@ files:
48
48
  - lib/geokit/geocoders/cached_multi_geocoder.rb
49
49
  has_rdoc: true
50
50
  homepage: http://geokit.rubyforge.org
51
- licenses: []
52
-
53
51
  post_install_message:
54
52
  rdoc_options:
55
53
  - --main
@@ -71,7 +69,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
71
69
  requirements: []
72
70
 
73
71
  rubyforge_project: geokit
74
- rubygems_version: 1.3.5
72
+ rubygems_version: 1.2.0
75
73
  signing_key:
76
74
  specification_version: 2
77
75
  summary: none