andre-geokit 1.3.2 → 1.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.markdown +38 -2
- data/lib/geokit.rb +1 -1
- data/lib/geokit/geocoders.rb +74 -14
- data/lib/geokit/mappable.rb +39 -5
- data/test/test_base_geocoder.rb +2 -1
- data/test/test_bounds.rb +23 -0
- data/test/test_google_geocoder.rb +49 -0
- data/test/test_latlng.rb +61 -0
- data/test/test_multi_geocoder.rb +49 -10
- data/test/test_multi_ip_geocoder.rb +5 -5
- metadata +1 -1
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
|
|
data/lib/geokit.rb
CHANGED
data/lib/geokit/geocoders.rb
CHANGED
@@ -119,8 +119,8 @@ module Geokit
|
|
119
119
|
# Main method which calls the do_geocode template method which subclasses
|
120
120
|
# are responsible for implementing. Returns a populated GeoLoc or an
|
121
121
|
# empty one with a failed success code.
|
122
|
-
def self.geocode(address)
|
123
|
-
res = do_geocode(address)
|
122
|
+
def self.geocode(address, options = {})
|
123
|
+
res = do_geocode(address, options)
|
124
124
|
return res.nil? ? GeoLoc.new : res
|
125
125
|
end
|
126
126
|
# Main method which calls the do_reverse_geocode template method which subclasses
|
@@ -172,8 +172,8 @@ module Geokit
|
|
172
172
|
def self.inherited(clazz)
|
173
173
|
class_name = clazz.name.split('::').last
|
174
174
|
src = <<-END_SRC
|
175
|
-
def self.#{Geokit::Inflector.underscore(class_name)}(address)
|
176
|
-
#{class_name}.geocode(address)
|
175
|
+
def self.#{Geokit::Inflector.underscore(class_name)}(address, options = {})
|
176
|
+
#{class_name}.geocode(address, options)
|
177
177
|
end
|
178
178
|
END_SRC
|
179
179
|
class_eval(src)
|
@@ -199,7 +199,7 @@ module Geokit
|
|
199
199
|
private
|
200
200
|
|
201
201
|
# Template method which does the geocode lookup.
|
202
|
-
def self.do_geocode(address)
|
202
|
+
def self.do_geocode(address, options = {})
|
203
203
|
raise ArgumentError('Geocoder.ca requires a GeoLoc argument') unless address.is_a?(GeoLoc)
|
204
204
|
url = construct_request(address)
|
205
205
|
res = self.call_geocoder_service(url)
|
@@ -241,7 +241,7 @@ module Geokit
|
|
241
241
|
class UsGeocoder < Geocoder
|
242
242
|
|
243
243
|
private
|
244
|
-
def self.do_geocode(address)
|
244
|
+
def self.do_geocode(address, options = {})
|
245
245
|
address_str = address.is_a?(GeoLoc) ? address.to_geocodeable_s : address
|
246
246
|
|
247
247
|
query = (address_str =~ /^\d{5}(?:-\d{4})?$/ ? "zip" : "address") + "=#{Geokit::Inflector::url_escape(address_str)}"
|
@@ -289,7 +289,7 @@ module Geokit
|
|
289
289
|
private
|
290
290
|
|
291
291
|
# Template method which does the geocode lookup.
|
292
|
-
def self.do_geocode(address)
|
292
|
+
def self.do_geocode(address, options = {})
|
293
293
|
address_str = address.is_a?(GeoLoc) ? address.to_geocodeable_s : address
|
294
294
|
url="http://api.local.yahoo.com/MapsService/V1/geocode?appid=#{Geokit::Geocoders::yahoo}&location=#{Geokit::Inflector::url_escape(address_str)}"
|
295
295
|
res = self.call_geocoder_service(url)
|
@@ -335,7 +335,7 @@ module Geokit
|
|
335
335
|
private
|
336
336
|
|
337
337
|
# Template method which does the geocode lookup.
|
338
|
-
def self.do_geocode(address)
|
338
|
+
def self.do_geocode(address, options = {})
|
339
339
|
address_str = address.is_a?(GeoLoc) ? address.to_geocodeable_s : address
|
340
340
|
# geonames need a space seperated search string
|
341
341
|
address_str.gsub!(/,/, " ")
|
@@ -400,15 +400,50 @@ module Geokit
|
|
400
400
|
end
|
401
401
|
|
402
402
|
# Template method which does the geocode lookup.
|
403
|
-
|
403
|
+
#
|
404
|
+
# Supports viewport/country code biasing
|
405
|
+
#
|
406
|
+
# ==== OPTIONS
|
407
|
+
# * :bias - This option makes the Google Geocoder return results biased to a particular
|
408
|
+
# country or viewport. Country code biasing is achieved by passing the ccTLD
|
409
|
+
# ('uk' for .co.uk, for example) as a :bias value. For a list of ccTLD's,
|
410
|
+
# look here: http://en.wikipedia.org/wiki/CcTLD. By default, the geocoder
|
411
|
+
# will be biased to results within the US (ccTLD .com).
|
412
|
+
#
|
413
|
+
# If you'd like the Google Geocoder to prefer results within a given viewport,
|
414
|
+
# you can pass a Geokit::Bounds object as the :bias value.
|
415
|
+
#
|
416
|
+
# ==== EXAMPLES
|
417
|
+
# # By default, the geocoder will return Syracuse, NY
|
418
|
+
# Geokit::Geocoders::GoogleGeocoder.geocode('Syracuse').country_code # => 'US'
|
419
|
+
# # With country code biasing, it returns Syracuse in Sicily, Italy
|
420
|
+
# Geokit::Geocoders::GoogleGeocoder.geocode('Syracuse', :bias => :it).country_code # => 'IT'
|
421
|
+
#
|
422
|
+
# # By default, the geocoder will return Winnetka, IL
|
423
|
+
# Geokit::Geocoders::GoogleGeocoder.geocode('Winnetka').state # => 'IL'
|
424
|
+
# # When biased to an bounding box around California, it will now return the Winnetka neighbourhood, CA
|
425
|
+
# bounds = Geokit::Bounds.normalize([34.074081, -118.694401], [34.321129, -118.399487])
|
426
|
+
# Geokit::Geocoders::GoogleGeocoder.geocode('Winnetka', :bias => bounds).state # => 'CA'
|
427
|
+
def self.do_geocode(address, options = {})
|
428
|
+
bias_str = options[:bias] ? construct_bias_string_from_options(options[:bias]) : ''
|
404
429
|
address_str = address.is_a?(GeoLoc) ? address.to_geocodeable_s : address
|
405
|
-
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")
|
430
|
+
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")
|
406
431
|
return GeoLoc.new if !res.is_a?(Net::HTTPSuccess)
|
407
432
|
xml = res.body
|
408
433
|
logger.debug "Google geocoding. Address: #{address}. Result: #{xml}"
|
409
434
|
return self.xml2GeoLoc(xml, address)
|
410
435
|
end
|
411
436
|
|
437
|
+
def self.construct_bias_string_from_options(bias)
|
438
|
+
if bias.is_a?(String) or bias.is_a?(Symbol)
|
439
|
+
# country code biasing
|
440
|
+
"&gl=#{bias.to_s.downcase}"
|
441
|
+
elsif bias.is_a?(Bounds)
|
442
|
+
# viewport biasing
|
443
|
+
"&ll=#{bias.center.ll}&spn=#{bias.to_span.ll}"
|
444
|
+
end
|
445
|
+
end
|
446
|
+
|
412
447
|
def self.xml2GeoLoc(xml, address="")
|
413
448
|
doc=REXML::Document.new(xml)
|
414
449
|
|
@@ -460,6 +495,14 @@ module Geokit
|
|
460
495
|
address_details=doc.elements['.//*[local-name() = "AddressDetails"]']
|
461
496
|
res.accuracy = address_details ? address_details.attributes['Accuracy'].to_i : 0
|
462
497
|
res.precision=%w{unknown country state state city zip zip+4 street address building}[res.accuracy]
|
498
|
+
|
499
|
+
# google returns a set of suggested boundaries for the geocoded result
|
500
|
+
if suggested_bounds = doc.elements['//LatLonBox']
|
501
|
+
res.suggested_bounds = Bounds.normalize(
|
502
|
+
[suggested_bounds.attributes['south'], suggested_bounds.attributes['west']],
|
503
|
+
[suggested_bounds.attributes['north'], suggested_bounds.attributes['east']])
|
504
|
+
end
|
505
|
+
|
463
506
|
res.success=true
|
464
507
|
|
465
508
|
return res
|
@@ -475,7 +518,7 @@ module Geokit
|
|
475
518
|
class GeoPluginGeocoder < Geocoder
|
476
519
|
private
|
477
520
|
|
478
|
-
def self.do_geocode(ip)
|
521
|
+
def self.do_geocode(ip, options = {})
|
479
522
|
return GeoLoc.new unless /^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})?$/.match(ip)
|
480
523
|
response = self.call_geocoder_service("http://www.geoplugin.net/xml.gp?ip=#{ip}")
|
481
524
|
return response.is_a?(Net::HTTPSuccess) ? parse_xml(response.body) : GeoLoc.new
|
@@ -508,7 +551,7 @@ module Geokit
|
|
508
551
|
# Given an IP address, returns a GeoLoc instance which contains latitude,
|
509
552
|
# longitude, city, and country code. Sets the success attribute to false if the ip
|
510
553
|
# parameter does not match an ip address.
|
511
|
-
def self.do_geocode(ip)
|
554
|
+
def self.do_geocode(ip, options = {})
|
512
555
|
return GeoLoc.new if '0.0.0.0' == ip
|
513
556
|
return GeoLoc.new unless /^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})?$/.match(ip)
|
514
557
|
url = "http://api.hostip.info/get_html.php?ip=#{ip}&position=true"
|
@@ -563,14 +606,14 @@ module Geokit
|
|
563
606
|
#
|
564
607
|
# The failover approach is crucial for production-grade apps, but is rarely used.
|
565
608
|
# 98% of your geocoding calls will be successful with the first call
|
566
|
-
def self.do_geocode(address)
|
609
|
+
def self.do_geocode(address, options = {})
|
567
610
|
geocode_ip = /^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})$/.match(address)
|
568
611
|
provider_order = geocode_ip ? Geokit::Geocoders::ip_provider_order : Geokit::Geocoders::provider_order
|
569
612
|
|
570
613
|
provider_order.each do |provider|
|
571
614
|
begin
|
572
615
|
klass = Geokit::Geocoders.const_get "#{Geokit::Inflector::camelize(provider.to_s)}Geocoder"
|
573
|
-
res = klass.send :geocode, address
|
616
|
+
res = klass.send :geocode, address, options
|
574
617
|
return res if res.success?
|
575
618
|
rescue
|
576
619
|
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}")
|
@@ -579,6 +622,23 @@ module Geokit
|
|
579
622
|
# If we get here, we failed completely.
|
580
623
|
GeoLoc.new
|
581
624
|
end
|
625
|
+
|
626
|
+
# This method will call one or more geocoders in the order specified in the
|
627
|
+
# configuration until one of the geocoders work, only this time it's going
|
628
|
+
# to try to reverse geocode a geographical point.
|
629
|
+
def self.do_reverse_geocode(latlng)
|
630
|
+
Geokit::Geocoders::provider_order.each do |provider|
|
631
|
+
begin
|
632
|
+
klass = Geokit::Geocoders.const_get "#{Geokit::Inflector::camelize(provider.to_s)}Geocoder"
|
633
|
+
res = klass.send :reverse_geocode, latlng
|
634
|
+
return res if res.success?
|
635
|
+
rescue
|
636
|
+
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}")
|
637
|
+
end
|
638
|
+
end
|
639
|
+
# If we get here, we failed completely.
|
640
|
+
GeoLoc.new
|
641
|
+
end
|
582
642
|
end
|
583
643
|
end
|
584
644
|
end
|
data/lib/geokit/mappable.rb
CHANGED
@@ -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
|
data/test/test_base_geocoder.rb
CHANGED
@@ -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
|
-
@
|
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
|
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
|
data/test/test_multi_geocoder.rb
CHANGED
@@ -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
|
|