rjaswal-geokit 1.5.0.2 → 1.5.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.markdown +5 -3
- data/lib/geokit/mappable.rb +57 -59
- data/test/test_geoloc.rb +1 -1
- data/test/test_geoplugin_geocoder.rb +2 -2
- data/test/test_google_geocoder.rb +1 -1
- data/test/test_google_geocoder3.rb +536 -0
- data/test/test_ipgeocoder.rb +32 -10
- data/test/test_yahoo_geocoder.rb +34 -16
- metadata +17 -5
data/README.markdown
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
The Geokit gem provides:
|
4
4
|
|
5
5
|
* Distance calculations between two points on the earth. Calculate the distance in miles, kilometers, or nautical miles, with all the trigonometry abstracted away by GeoKit.
|
6
|
-
* Geocoding from multiple providers. It supports Google, Yahoo, Geocoder.us, and Geocoder.ca geocoders, and others. It provides a uniform response structure from all of them.
|
6
|
+
* Geocoding from multiple providers. It supports Google (API v2), Google (API v3), Bing, Yahoo, Geocoder.us, and Geocoder.ca geocoders, and others. It provides a uniform response structure from all of them.
|
7
7
|
It also provides a fail-over mechanism, in case your input fails to geocode in one service.
|
8
8
|
* Rectangular bounds calculations: is a point within a given rectangular bounds?
|
9
9
|
* Heading and midpoint calculations
|
@@ -16,7 +16,9 @@ Combine this gem with the [geokit-rails plugin](http://github.com/andre/geokit-r
|
|
16
16
|
|
17
17
|
## INSTALL
|
18
18
|
|
19
|
-
sudo gem install geokit
|
19
|
+
sudo gem install rjaswal-geokit
|
20
|
+
or for latest use
|
21
|
+
./script/plugin install git://github.com/rjaswal/geokit-gem.git
|
20
22
|
|
21
23
|
## QUICK START
|
22
24
|
|
@@ -54,7 +56,7 @@ If you're using this gem by itself, here are the configuration options:
|
|
54
56
|
# This is the timeout value in seconds to be used for calls to the geocoder web
|
55
57
|
# services. For no timeout at all, comment out the setting. The timeout unit
|
56
58
|
# is in seconds.
|
57
|
-
Geokit::Geocoders::
|
59
|
+
Geokit::Geocoders::request_timeout = 3
|
58
60
|
|
59
61
|
# These settings are used if web service calls must be routed through a proxy.
|
60
62
|
# These setting can be nil if not needed, otherwise, addr and port must be
|
data/lib/geokit/mappable.rb
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
#require 'forwardable'
|
2
|
-
|
3
1
|
module Geokit
|
4
2
|
# Contains class and instance methods providing distance calcuation services. This
|
5
3
|
# module is meant to be mixed into classes containing lat and lng attributes where
|
@@ -22,12 +20,12 @@ module Geokit
|
|
22
20
|
KMS_PER_LATITUDE_DEGREE = MILES_PER_LATITUDE_DEGREE * KMS_PER_MILE
|
23
21
|
NMS_PER_LATITUDE_DEGREE = MILES_PER_LATITUDE_DEGREE * NMS_PER_MILE
|
24
22
|
LATITUDE_DEGREES = EARTH_RADIUS_IN_MILES / MILES_PER_LATITUDE_DEGREE
|
25
|
-
|
23
|
+
|
26
24
|
# Mix below class methods into the includer.
|
27
25
|
def self.included(receiver) # :nodoc:
|
28
26
|
receiver.extend ClassMethods
|
29
27
|
end
|
30
|
-
|
28
|
+
|
31
29
|
module ClassMethods #:nodoc:
|
32
30
|
# Returns the distance between two points. The from and to parameters are
|
33
31
|
# required to have lat and lng attributes. Valid options are:
|
@@ -43,15 +41,15 @@ module Geokit
|
|
43
41
|
when :sphere
|
44
42
|
begin
|
45
43
|
units_sphere_multiplier(units) *
|
46
|
-
|
47
|
-
|
48
|
-
|
44
|
+
Math.acos( Math.sin(deg2rad(from.lat)) * Math.sin(deg2rad(to.lat)) +
|
45
|
+
Math.cos(deg2rad(from.lat)) * Math.cos(deg2rad(to.lat)) *
|
46
|
+
Math.cos(deg2rad(to.lng) - deg2rad(from.lng)))
|
49
47
|
rescue Errno::EDOM
|
50
48
|
0.0
|
51
49
|
end
|
52
50
|
when :flat
|
53
51
|
Math.sqrt((units_per_latitude_degree(units)*(from.lat-to.lat))**2 +
|
54
|
-
|
52
|
+
(units_per_longitude_degree(from.lat, units)*(from.lng-to.lng))**2)
|
55
53
|
end
|
56
54
|
end
|
57
55
|
|
@@ -69,23 +67,23 @@ module Geokit
|
|
69
67
|
x=Math.cos(from_lat)*Math.sin(to_lat)-Math.sin(from_lat)*Math.cos(to_lat)*Math.cos(d_lng)
|
70
68
|
heading=to_heading(Math.atan2(y,x))
|
71
69
|
end
|
72
|
-
|
70
|
+
|
73
71
|
# Given a start point, distance, and heading (in degrees), provides
|
74
72
|
# an endpoint. Returns a LatLng instance. Typically, the instance method
|
75
73
|
# will be used instead of this method.
|
76
74
|
def endpoint(start,heading, distance, options={})
|
77
75
|
units = options[:units] || Geokit::default_units
|
78
76
|
radius = case units
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
77
|
+
when :kms; EARTH_RADIUS_IN_KMS
|
78
|
+
when :nms; EARTH_RADIUS_IN_NMS
|
79
|
+
else EARTH_RADIUS_IN_MILES
|
80
|
+
end
|
83
81
|
start=Geokit::LatLng.normalize(start)
|
84
82
|
lat=deg2rad(start.lat)
|
85
83
|
lng=deg2rad(start.lng)
|
86
84
|
heading=deg2rad(heading)
|
87
85
|
distance=distance.to_f
|
88
|
-
|
86
|
+
|
89
87
|
end_lat=Math.asin(Math.sin(lat)*Math.cos(distance/radius) +
|
90
88
|
Math.cos(lat)*Math.sin(distance/radius)*Math.cos(heading))
|
91
89
|
|
@@ -103,29 +101,29 @@ module Geokit
|
|
103
101
|
from=Geokit::LatLng.normalize(from)
|
104
102
|
|
105
103
|
units = options[:units] || Geokit::default_units
|
106
|
-
|
104
|
+
|
107
105
|
heading=from.heading_to(to)
|
108
106
|
distance=from.distance_to(to,options)
|
109
107
|
midpoint=from.endpoint(heading,distance/2,options)
|
110
108
|
end
|
111
|
-
|
109
|
+
|
112
110
|
# Geocodes a location using the multi geocoder.
|
113
111
|
def geocode(location, options = {})
|
114
112
|
res = Geocoders::MultiGeocoder.geocode(location, options)
|
115
113
|
return res if res.success?
|
116
114
|
raise Geokit::Geocoders::GeocodeError
|
117
115
|
end
|
118
|
-
|
116
|
+
|
119
117
|
protected
|
120
|
-
|
118
|
+
|
121
119
|
def deg2rad(degrees)
|
122
120
|
degrees.to_f / 180.0 * Math::PI
|
123
121
|
end
|
124
|
-
|
122
|
+
|
125
123
|
def rad2deg(rad)
|
126
124
|
rad.to_f * 180.0 / Math::PI
|
127
125
|
end
|
128
|
-
|
126
|
+
|
129
127
|
def to_heading(rad)
|
130
128
|
(rad2deg(rad)+360)%360
|
131
129
|
end
|
@@ -133,36 +131,36 @@ module Geokit
|
|
133
131
|
# Returns the multiplier used to obtain the correct distance units.
|
134
132
|
def units_sphere_multiplier(units)
|
135
133
|
case units
|
136
|
-
|
137
|
-
|
138
|
-
|
134
|
+
when :kms; EARTH_RADIUS_IN_KMS
|
135
|
+
when :nms; EARTH_RADIUS_IN_NMS
|
136
|
+
else EARTH_RADIUS_IN_MILES
|
139
137
|
end
|
140
138
|
end
|
141
139
|
|
142
140
|
# Returns the number of units per latitude degree.
|
143
141
|
def units_per_latitude_degree(units)
|
144
142
|
case units
|
145
|
-
|
146
|
-
|
147
|
-
|
143
|
+
when :kms; KMS_PER_LATITUDE_DEGREE
|
144
|
+
when :nms; NMS_PER_LATITUDE_DEGREE
|
145
|
+
else MILES_PER_LATITUDE_DEGREE
|
148
146
|
end
|
149
147
|
end
|
150
|
-
|
148
|
+
|
151
149
|
# Returns the number units per longitude degree.
|
152
150
|
def units_per_longitude_degree(lat, units)
|
153
151
|
miles_per_longitude_degree = (LATITUDE_DEGREES * Math.cos(lat * PI_DIV_RAD)).abs
|
154
152
|
case units
|
155
|
-
|
156
|
-
|
157
|
-
|
153
|
+
when :kms; miles_per_longitude_degree * KMS_PER_MILE
|
154
|
+
when :nms; miles_per_longitude_degree * NMS_PER_MILE
|
155
|
+
else miles_per_longitude_degree
|
158
156
|
end
|
159
157
|
end
|
160
158
|
end
|
161
|
-
|
159
|
+
|
162
160
|
# -----------------------------------------------------------------------------------------------
|
163
161
|
# Instance methods below here
|
164
162
|
# -----------------------------------------------------------------------------------------------
|
165
|
-
|
163
|
+
|
166
164
|
# Extracts a LatLng instance. Use with models that are acts_as_mappable
|
167
165
|
def to_lat_lng
|
168
166
|
return self if instance_of?(Geokit::LatLng) || instance_of?(Geokit::GeoLoc)
|
@@ -190,7 +188,7 @@ module Geokit
|
|
190
188
|
def heading_from(other)
|
191
189
|
self.class.heading_between(other,self)
|
192
190
|
end
|
193
|
-
|
191
|
+
|
194
192
|
# Returns the endpoint, given a heading (in degrees) and distance.
|
195
193
|
# Valid option:
|
196
194
|
# :units - valid values are :miles, :kms, or :nms (:miles is the default)
|
@@ -204,7 +202,7 @@ module Geokit
|
|
204
202
|
def midpoint_to(other, options={})
|
205
203
|
self.class.midpoint_between(self,other,options)
|
206
204
|
end
|
207
|
-
|
205
|
+
|
208
206
|
end
|
209
207
|
|
210
208
|
class LatLng
|
@@ -235,12 +233,12 @@ module Geokit
|
|
235
233
|
def ll
|
236
234
|
"#{lat},#{lng}"
|
237
235
|
end
|
238
|
-
|
236
|
+
|
239
237
|
#returns a string with comma-separated lat,lng values
|
240
238
|
def to_s
|
241
239
|
ll
|
242
240
|
end
|
243
|
-
|
241
|
+
|
244
242
|
#returns a two-element array
|
245
243
|
def to_a
|
246
244
|
[lat,lng]
|
@@ -250,15 +248,15 @@ module Geokit
|
|
250
248
|
def ==(other)
|
251
249
|
other.is_a?(LatLng) ? self.lat == other.lat && self.lng == other.lng : false
|
252
250
|
end
|
253
|
-
|
251
|
+
|
254
252
|
def hash
|
255
253
|
lat.hash + lng.hash
|
256
254
|
end
|
257
|
-
|
255
|
+
|
258
256
|
def eql?(other)
|
259
257
|
self == other
|
260
258
|
end
|
261
|
-
|
259
|
+
|
262
260
|
# A *class* method to take anything which can be inferred as a point and generate
|
263
261
|
# a LatLng from it. You should use this anything you're not sure what the input is,
|
264
262
|
# and want to deal with it as a LatLng if at all possible. Can take:
|
@@ -271,7 +269,7 @@ module Geokit
|
|
271
269
|
def self.normalize(thing,other=nil)
|
272
270
|
# if an 'other' thing is supplied, normalize the input by creating an array of two elements
|
273
271
|
thing=[thing,other] if other
|
274
|
-
|
272
|
+
|
275
273
|
if thing.is_a?(String)
|
276
274
|
thing.strip!
|
277
275
|
if match=thing.match(/(\-?\d+\.?\d*)[, ] ?(\-?\d+\.?\d*)$/)
|
@@ -288,10 +286,10 @@ module Geokit
|
|
288
286
|
elsif thing.class.respond_to?(:acts_as_mappable) && thing.class.respond_to?(:distance_column_name)
|
289
287
|
return thing.to_lat_lng
|
290
288
|
end
|
291
|
-
|
289
|
+
|
292
290
|
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
291
|
end
|
294
|
-
|
292
|
+
|
295
293
|
# Reverse geocodes a LatLng object using the MultiGeocoder (default), or optionally
|
296
294
|
# using a geocoder of your choosing. Returns a new Geokit::GeoLoc object
|
297
295
|
#
|
@@ -313,7 +311,7 @@ module Geokit
|
|
313
311
|
else
|
314
312
|
raise ArgumentError.new("#{options[:using]} is not a valid geocoder.")
|
315
313
|
end
|
316
|
-
|
314
|
+
|
317
315
|
provider.send(:reverse_geocode, self)
|
318
316
|
end
|
319
317
|
end
|
@@ -355,7 +353,7 @@ module Geokit
|
|
355
353
|
# Constructor expects a hash of symbols to correspond with attributes.
|
356
354
|
def initialize(h={})
|
357
355
|
@all = [self]
|
358
|
-
|
356
|
+
|
359
357
|
@street_address=h[:street_address]
|
360
358
|
@street_number=nil
|
361
359
|
@street_name=nil
|
@@ -374,7 +372,7 @@ module Geokit
|
|
374
372
|
def is_us?
|
375
373
|
country_code == 'US'
|
376
374
|
end
|
377
|
-
|
375
|
+
|
378
376
|
def success?
|
379
377
|
success == true
|
380
378
|
end
|
@@ -419,7 +417,7 @@ module Geokit
|
|
419
417
|
@street_address = address
|
420
418
|
end
|
421
419
|
end
|
422
|
-
|
420
|
+
|
423
421
|
# Returns a comma-delimited string consisting of the street address, city, state,
|
424
422
|
# zip, and country code. Only includes those attributes that are non-blank.
|
425
423
|
def to_geocodeable_s
|
@@ -427,7 +425,7 @@ module Geokit
|
|
427
425
|
a.delete_if { |e| !e || e == '' }
|
428
426
|
a.join(', ')
|
429
427
|
end
|
430
|
-
|
428
|
+
|
431
429
|
def to_yaml_properties
|
432
430
|
(instance_variables - ['@all']).sort
|
433
431
|
end
|
@@ -437,33 +435,33 @@ module Geokit
|
|
437
435
|
"Provider: #{provider}\nStreet: #{street_address}\nCity: #{city}\nState: #{state}\nZip: #{zip}\nLatitude: #{lat}\nLongitude: #{lng}\nCountry: #{country_code}\nSuccess: #{success}"
|
438
436
|
end
|
439
437
|
end
|
440
|
-
|
438
|
+
|
441
439
|
# Bounds represents a rectangular bounds, defined by the SW and NE corners
|
442
440
|
class Bounds
|
443
441
|
# sw and ne are LatLng objects
|
444
442
|
attr_accessor :sw, :ne
|
445
|
-
|
443
|
+
|
446
444
|
# provide sw and ne to instantiate a new Bounds instance
|
447
445
|
def initialize(sw,ne)
|
448
446
|
raise ArgumentError if !(sw.is_a?(Geokit::LatLng) && ne.is_a?(Geokit::LatLng))
|
449
447
|
@sw,@ne=sw,ne
|
450
448
|
end
|
451
|
-
|
449
|
+
|
452
450
|
#returns the a single point which is the center of the rectangular bounds
|
453
451
|
def center
|
454
452
|
@sw.midpoint_to(@ne)
|
455
453
|
end
|
456
|
-
|
454
|
+
|
457
455
|
# a simple string representation:sw,ne
|
458
456
|
def to_s
|
459
457
|
"#{@sw.to_s},#{@ne.to_s}"
|
460
458
|
end
|
461
|
-
|
459
|
+
|
462
460
|
# a two-element array of two-element arrays: sw,ne
|
463
461
|
def to_a
|
464
462
|
[@sw.to_a, @ne.to_a]
|
465
463
|
end
|
466
|
-
|
464
|
+
|
467
465
|
# Returns true if the bounds contain the passed point.
|
468
466
|
# allows for bounds which cross the meridian
|
469
467
|
def contains?(point)
|
@@ -476,7 +474,7 @@ module Geokit
|
|
476
474
|
end
|
477
475
|
res
|
478
476
|
end
|
479
|
-
|
477
|
+
|
480
478
|
# returns true if the bounds crosses the international dateline
|
481
479
|
def crosses_meridian?
|
482
480
|
@sw.lng > @ne.lng
|
@@ -487,7 +485,7 @@ module Geokit
|
|
487
485
|
def ==(other)
|
488
486
|
other.is_a?(Bounds) ? self.sw == other.sw && self.ne == other.ne : false
|
489
487
|
end
|
490
|
-
|
488
|
+
|
491
489
|
# Equivalent to Google Maps API's .toSpan() method on GLatLng's.
|
492
490
|
#
|
493
491
|
# Returns a LatLng object, whose coordinates represent the size of a rectangle
|
@@ -497,9 +495,9 @@ module Geokit
|
|
497
495
|
lng_span = (crosses_meridian? ? 360 + @ne.lng - @sw.lng : @ne.lng - @sw.lng).abs
|
498
496
|
Geokit::LatLng.new(lat_span, lng_span)
|
499
497
|
end
|
500
|
-
|
498
|
+
|
501
499
|
class <<self
|
502
|
-
|
500
|
+
|
503
501
|
# returns an instance of bounds which completely encompases the given circle
|
504
502
|
def from_point_and_radius(point,radius,options={})
|
505
503
|
point=LatLng.normalize(point)
|
@@ -511,7 +509,7 @@ module Geokit
|
|
511
509
|
ne=Geokit::LatLng.new(p0.lat,p90.lng)
|
512
510
|
Geokit::Bounds.new(sw,ne)
|
513
511
|
end
|
514
|
-
|
512
|
+
|
515
513
|
# Takes two main combinations of arguments to create a bounds:
|
516
514
|
# point,point (this is the only one which takes two arguments
|
517
515
|
# [point,point]
|
@@ -521,7 +519,7 @@ module Geokit
|
|
521
519
|
def normalize (thing,other=nil)
|
522
520
|
# maybe this will be simple -- an actual bounds object is passed, and we can all go home
|
523
521
|
return thing if thing.is_a? Bounds
|
524
|
-
|
522
|
+
|
525
523
|
# no? OK, if there's no "other," the thing better be a two-element array
|
526
524
|
thing,other=thing if !other && thing.is_a?(Array) && thing.size==2
|
527
525
|
|
data/test/test_geoloc.rb
CHANGED
@@ -65,7 +65,7 @@ class GeoLocTest < Test::Unit::TestCase #:nodoc: all
|
|
65
65
|
@loc.zip = '94105'
|
66
66
|
@loc.country_code = 'US'
|
67
67
|
assert_equal(
|
68
|
-
"--- !ruby/object:Geokit::GeoLoc \ncity: San Francisco\ncountry_code: US\nfull_address: \nlat: \nlng: \nprecision: unknown\nprovince: \nstate: CA\nstreet_address: \nsuccess: false\nzip: \"94105\"\n",
|
68
|
+
"--- !ruby/object:Geokit::GeoLoc \ncity: San Francisco\ncountry_code: US\nfull_address: \nlat: \nlng: \nprecision: unknown\nprovince: \nstate: CA\nstreet_address: \nstreet_name: \nstreet_number: \nsuccess: false\nzip: \"94105\"\n",
|
69
69
|
@loc.to_yaml)
|
70
70
|
end
|
71
71
|
|
@@ -33,8 +33,8 @@ class IpGeocoderTest < BaseGeocoderTest #:nodoc: all
|
|
33
33
|
GeoKit::Geocoders::GeoPluginGeocoder.expects(:call_geocoder_service).with(url).returns(success)
|
34
34
|
location = GeoKit::Geocoders::GeoPluginGeocoder.geocode('200.150.38.66')
|
35
35
|
assert_not_nil location
|
36
|
-
assert_equal
|
37
|
-
assert_equal
|
36
|
+
assert_equal(-19.916700, location.lat)
|
37
|
+
assert_equal(-43.933300, location.lng)
|
38
38
|
assert_equal "Belo Horizonte", location.city
|
39
39
|
assert_equal "Minas Gerais", location.state
|
40
40
|
assert_equal "BR", location.country_code
|
@@ -186,7 +186,7 @@ class GoogleGeocoderTest < BaseGeocoderTest #:nodoc: all
|
|
186
186
|
|
187
187
|
assert_equal "Plaza de la Puerta del Sol, 28013, Madrid, Spain", res.full_address
|
188
188
|
assert_equal "28013", res.zip
|
189
|
-
assert_equal "Plaza
|
189
|
+
assert_equal "Plaza de la Puerta del Sol", res.street_address
|
190
190
|
end
|
191
191
|
|
192
192
|
def test_country_code_biasing
|
@@ -0,0 +1,536 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'test_base_geocoder')
|
2
|
+
|
3
|
+
Geokit::Geocoders::google = 'Google'
|
4
|
+
|
5
|
+
class GoogleGeocoder3Test < BaseGeocoderTest #:nodoc: all
|
6
|
+
|
7
|
+
GOOGLE3_FULL=%q/
|
8
|
+
{
|
9
|
+
"status": "OK",
|
10
|
+
"results": [ {
|
11
|
+
"types": [ "street_address" ],
|
12
|
+
"formatted_address": "100 Spear St, San Francisco, CA 94105, USA",
|
13
|
+
"address_components": [ {
|
14
|
+
"long_name": "100",
|
15
|
+
"short_name": "100",
|
16
|
+
"types": [ "street_number" ]
|
17
|
+
}, {
|
18
|
+
"long_name": "Spear St",
|
19
|
+
"short_name": "Spear St",
|
20
|
+
"types": [ "route" ]
|
21
|
+
}, {
|
22
|
+
"long_name": "San Francisco",
|
23
|
+
"short_name": "San Francisco",
|
24
|
+
"types": [ "locality", "political" ]
|
25
|
+
}, {
|
26
|
+
"long_name": "San Francisco",
|
27
|
+
"short_name": "San Francisco",
|
28
|
+
"types": [ "administrative_area_level_3", "political" ]
|
29
|
+
}, {
|
30
|
+
"long_name": "San Francisco",
|
31
|
+
"short_name": "San Francisco",
|
32
|
+
"types": [ "administrative_area_level_2", "political" ]
|
33
|
+
}, {
|
34
|
+
"long_name": "California",
|
35
|
+
"short_name": "CA",
|
36
|
+
"types": [ "administrative_area_level_1", "political" ]
|
37
|
+
}, {
|
38
|
+
"long_name": "United States",
|
39
|
+
"short_name": "US",
|
40
|
+
"types": [ "country", "political" ]
|
41
|
+
}, {
|
42
|
+
"long_name": "94105",
|
43
|
+
"short_name": "94105",
|
44
|
+
"types": [ "postal_code" ]
|
45
|
+
} ],
|
46
|
+
"geometry": {
|
47
|
+
"location": {
|
48
|
+
"lat": 37.7921509,
|
49
|
+
"lng": -122.3940000
|
50
|
+
},
|
51
|
+
"location_type": "ROOFTOP",
|
52
|
+
"viewport": {
|
53
|
+
"southwest": {
|
54
|
+
"lat": 37.7890033,
|
55
|
+
"lng": -122.3971476
|
56
|
+
},
|
57
|
+
"northeast": {
|
58
|
+
"lat": 37.7952985,
|
59
|
+
"lng": -122.3908524
|
60
|
+
}
|
61
|
+
}
|
62
|
+
}
|
63
|
+
} ]
|
64
|
+
}
|
65
|
+
/.strip
|
66
|
+
|
67
|
+
GOOGLE3_CITY=%q/
|
68
|
+
{
|
69
|
+
"status": "OK",
|
70
|
+
"results": [ {
|
71
|
+
"types": [ "locality", "political" ],
|
72
|
+
"formatted_address": "San Francisco, CA, USA",
|
73
|
+
"address_components": [ {
|
74
|
+
"long_name": "San Francisco",
|
75
|
+
"short_name": "San Francisco",
|
76
|
+
"types": [ "locality", "political" ]
|
77
|
+
}, {
|
78
|
+
"long_name": "San Francisco",
|
79
|
+
"short_name": "San Francisco",
|
80
|
+
"types": [ "administrative_area_level_2", "political" ]
|
81
|
+
}, {
|
82
|
+
"long_name": "California",
|
83
|
+
"short_name": "CA",
|
84
|
+
"types": [ "administrative_area_level_1", "political" ]
|
85
|
+
}, {
|
86
|
+
"long_name": "United States",
|
87
|
+
"short_name": "US",
|
88
|
+
"types": [ "country", "political" ]
|
89
|
+
} ],
|
90
|
+
"geometry": {
|
91
|
+
"location": {
|
92
|
+
"lat": 37.7749295,
|
93
|
+
"lng": -122.4194155
|
94
|
+
},
|
95
|
+
"location_type": "APPROXIMATE",
|
96
|
+
"viewport": {
|
97
|
+
"southwest": {
|
98
|
+
"lat": 37.7043396,
|
99
|
+
"lng": -122.5474749
|
100
|
+
},
|
101
|
+
"northeast": {
|
102
|
+
"lat": 37.8454521,
|
103
|
+
"lng": -122.2913561
|
104
|
+
}
|
105
|
+
},
|
106
|
+
"bounds": {
|
107
|
+
"southwest": {
|
108
|
+
"lat": 37.7034000,
|
109
|
+
"lng": -122.5270000
|
110
|
+
},
|
111
|
+
"northeast": {
|
112
|
+
"lat": 37.8120000,
|
113
|
+
"lng": -122.3482000
|
114
|
+
}
|
115
|
+
}
|
116
|
+
}
|
117
|
+
} ]
|
118
|
+
}
|
119
|
+
/.strip
|
120
|
+
GOOGLE3_MULTI=%q/
|
121
|
+
{
|
122
|
+
"status": "OK",
|
123
|
+
"results": [ {
|
124
|
+
"types": [ "street_address" ],
|
125
|
+
"formatted_address": "Via Sandro Pertini, 8, 20010 Mesero MI, Italy",
|
126
|
+
"address_components": [ {
|
127
|
+
"long_name": "8",
|
128
|
+
"short_name": "8",
|
129
|
+
"types": [ "street_number" ]
|
130
|
+
}, {
|
131
|
+
"long_name": "Via Sandro Pertini",
|
132
|
+
"short_name": "Via Sandro Pertini",
|
133
|
+
"types": [ "route" ]
|
134
|
+
}, {
|
135
|
+
"long_name": "Mesero",
|
136
|
+
"short_name": "Mesero",
|
137
|
+
"types": [ "locality", "political" ]
|
138
|
+
}, {
|
139
|
+
"long_name": "Milan",
|
140
|
+
"short_name": "MI",
|
141
|
+
"types": [ "administrative_area_level_2", "political" ]
|
142
|
+
}, {
|
143
|
+
"long_name": "Lombardy",
|
144
|
+
"short_name": "Lombardy",
|
145
|
+
"types": [ "administrative_area_level_1", "political" ]
|
146
|
+
}, {
|
147
|
+
"long_name": "Italy",
|
148
|
+
"short_name": "IT",
|
149
|
+
"types": [ "country", "political" ]
|
150
|
+
}, {
|
151
|
+
"long_name": "20010",
|
152
|
+
"short_name": "20010",
|
153
|
+
"types": [ "postal_code" ]
|
154
|
+
} ],
|
155
|
+
"geometry": {
|
156
|
+
"location": {
|
157
|
+
"lat": 45.4966218,
|
158
|
+
"lng": 8.8526940
|
159
|
+
},
|
160
|
+
"location_type": "RANGE_INTERPOLATED",
|
161
|
+
"viewport": {
|
162
|
+
"southwest": {
|
163
|
+
"lat": 45.4934754,
|
164
|
+
"lng": 8.8495559
|
165
|
+
},
|
166
|
+
"northeast": {
|
167
|
+
"lat": 45.4997707,
|
168
|
+
"lng": 8.8558512
|
169
|
+
}
|
170
|
+
},
|
171
|
+
"bounds": {
|
172
|
+
"southwest": {
|
173
|
+
"lat": 45.4966218,
|
174
|
+
"lng": 8.8526940
|
175
|
+
},
|
176
|
+
"northeast": {
|
177
|
+
"lat": 45.4966243,
|
178
|
+
"lng": 8.8527131
|
179
|
+
}
|
180
|
+
}
|
181
|
+
},
|
182
|
+
"partial_match": true
|
183
|
+
},
|
184
|
+
{
|
185
|
+
"types": [ "route" ],
|
186
|
+
"formatted_address": "Via Sandro Pertini, 20010 Ossona MI, Italy",
|
187
|
+
"address_components": [ {
|
188
|
+
"long_name": "Via Sandro Pertini",
|
189
|
+
"short_name": "Via Sandro Pertini",
|
190
|
+
"types": [ "route" ]
|
191
|
+
}, {
|
192
|
+
"long_name": "Ossona",
|
193
|
+
"short_name": "Ossona",
|
194
|
+
"types": [ "locality", "political" ]
|
195
|
+
}, {
|
196
|
+
"long_name": "Milan",
|
197
|
+
"short_name": "MI",
|
198
|
+
"types": [ "administrative_area_level_2", "political" ]
|
199
|
+
}, {
|
200
|
+
"long_name": "Lombardy",
|
201
|
+
"short_name": "Lombardy",
|
202
|
+
"types": [ "administrative_area_level_1", "political" ]
|
203
|
+
}, {
|
204
|
+
"long_name": "Italy",
|
205
|
+
"short_name": "IT",
|
206
|
+
"types": [ "country", "political" ]
|
207
|
+
}, {
|
208
|
+
"long_name": "20010",
|
209
|
+
"short_name": "20010",
|
210
|
+
"types": [ "postal_code" ]
|
211
|
+
} ],
|
212
|
+
"geometry": {
|
213
|
+
"location": {
|
214
|
+
"lat": 45.5074444,
|
215
|
+
"lng": 8.9023200
|
216
|
+
},
|
217
|
+
"location_type": "GEOMETRIC_CENTER",
|
218
|
+
"viewport": {
|
219
|
+
"southwest": {
|
220
|
+
"lat": 45.5043320,
|
221
|
+
"lng": 8.8990670
|
222
|
+
},
|
223
|
+
"northeast": {
|
224
|
+
"lat": 45.5106273,
|
225
|
+
"lng": 8.9053622
|
226
|
+
}
|
227
|
+
},
|
228
|
+
"bounds": {
|
229
|
+
"southwest": {
|
230
|
+
"lat": 45.5064427,
|
231
|
+
"lng": 8.9020024
|
232
|
+
},
|
233
|
+
"northeast": {
|
234
|
+
"lat": 45.5085166,
|
235
|
+
"lng": 8.9024268
|
236
|
+
}
|
237
|
+
}
|
238
|
+
}
|
239
|
+
}
|
240
|
+
]
|
241
|
+
}
|
242
|
+
/.strip
|
243
|
+
GOOGLE3_REVERSE_MADRID=%q/
|
244
|
+
{
|
245
|
+
"status": "OK",
|
246
|
+
"results": [ {
|
247
|
+
"types": [ ],
|
248
|
+
"formatted_address": "Calle de las Carretas, 28013 Madrid, Spain",
|
249
|
+
"address_components": [ {
|
250
|
+
"long_name": "Calle de las Carretas",
|
251
|
+
"short_name": "Calle de las Carretas",
|
252
|
+
"types": [ "route" ]
|
253
|
+
}, {
|
254
|
+
"long_name": "Madrid",
|
255
|
+
"short_name": "Madrid",
|
256
|
+
"types": [ "locality", "political" ]
|
257
|
+
}, {
|
258
|
+
"long_name": "Madrid",
|
259
|
+
"short_name": "M",
|
260
|
+
"types": [ "administrative_area_level_2", "political" ]
|
261
|
+
}, {
|
262
|
+
"long_name": "Madrid",
|
263
|
+
"short_name": "Madrid",
|
264
|
+
"types": [ "administrative_area_level_1", "political" ]
|
265
|
+
}, {
|
266
|
+
"long_name": "Spain",
|
267
|
+
"short_name": "ES",
|
268
|
+
"types": [ "country", "political" ]
|
269
|
+
}, {
|
270
|
+
"long_name": "28013",
|
271
|
+
"short_name": "28013",
|
272
|
+
"types": [ "postal_code" ]
|
273
|
+
} ],
|
274
|
+
"geometry": {
|
275
|
+
"location": {
|
276
|
+
"lat": 40.4166824,
|
277
|
+
"lng": -3.7033411
|
278
|
+
},
|
279
|
+
"location_type": "APPROXIMATE",
|
280
|
+
"viewport": {
|
281
|
+
"southwest": {
|
282
|
+
"lat": 40.4135351,
|
283
|
+
"lng": -3.7064880
|
284
|
+
},
|
285
|
+
"northeast": {
|
286
|
+
"lat": 40.4198303,
|
287
|
+
"lng": -3.7001927
|
288
|
+
}
|
289
|
+
},
|
290
|
+
"bounds": {
|
291
|
+
"southwest": {
|
292
|
+
"lat": 40.4166419,
|
293
|
+
"lng": -3.7033685
|
294
|
+
},
|
295
|
+
"northeast": {
|
296
|
+
"lat": 40.4167235,
|
297
|
+
"lng": -3.7033122
|
298
|
+
}
|
299
|
+
}
|
300
|
+
}
|
301
|
+
} ]
|
302
|
+
}
|
303
|
+
/
|
304
|
+
GOOGLE3_COUNTRY_CODE_BIASED_RESULT=%q/
|
305
|
+
{
|
306
|
+
"status": "OK",
|
307
|
+
"results": [ {
|
308
|
+
"types": [ "administrative_area_level_2", "political" ],
|
309
|
+
"formatted_address": "Syracuse, Italy",
|
310
|
+
"address_components": [ {
|
311
|
+
"long_name": "Syracuse",
|
312
|
+
"short_name": "SR",
|
313
|
+
"types": [ "administrative_area_level_2", "political" ]
|
314
|
+
}, {
|
315
|
+
"long_name": "Sicily",
|
316
|
+
"short_name": "Sicily",
|
317
|
+
"types": [ "administrative_area_level_1", "political" ]
|
318
|
+
}, {
|
319
|
+
"long_name": "Italy",
|
320
|
+
"short_name": "IT",
|
321
|
+
"types": [ "country", "political" ]
|
322
|
+
} ],
|
323
|
+
"geometry": {
|
324
|
+
"location": {
|
325
|
+
"lat": 37.0630218,
|
326
|
+
"lng": 14.9856176
|
327
|
+
},
|
328
|
+
"location_type": "APPROXIMATE",
|
329
|
+
"viewport": {
|
330
|
+
"southwest": {
|
331
|
+
"lat": 36.7775664,
|
332
|
+
"lng": 14.4733800
|
333
|
+
},
|
334
|
+
"northeast": {
|
335
|
+
"lat": 37.3474070,
|
336
|
+
"lng": 15.4978552
|
337
|
+
}
|
338
|
+
},
|
339
|
+
"bounds": {
|
340
|
+
"southwest": {
|
341
|
+
"lat": 36.6441736,
|
342
|
+
"lng": 14.7724913
|
343
|
+
},
|
344
|
+
"northeast": {
|
345
|
+
"lat": 37.4125978,
|
346
|
+
"lng": 15.3367367
|
347
|
+
}
|
348
|
+
}
|
349
|
+
}
|
350
|
+
} ]
|
351
|
+
}
|
352
|
+
/
|
353
|
+
GOOGLE3_TOO_MANY=%q/
|
354
|
+
{
|
355
|
+
"status": "OVER_QUERY_LIMIT"
|
356
|
+
}
|
357
|
+
/
|
358
|
+
def setup
|
359
|
+
super
|
360
|
+
@google_full_hash = {:street_address=>"100 Spear St", :city=>"San Francisco", :state=>"CA", :zip=>"94105", :country_code=>"US"}
|
361
|
+
@google_city_hash = {:city=>"San Francisco", :state=>"CA"}
|
362
|
+
|
363
|
+
@google_full_loc = Geokit::GeoLoc.new(@google_full_hash)
|
364
|
+
@google_city_loc = Geokit::GeoLoc.new(@google_city_hash)
|
365
|
+
end
|
366
|
+
|
367
|
+
def test_google3_full_address
|
368
|
+
response = MockSuccess.new
|
369
|
+
response.expects(:body).returns(GOOGLE3_FULL)
|
370
|
+
url = "http://maps.google.com/maps/api/geocode/json?sensor=false&address=#{Geokit::Inflector::url_escape(@address)}"
|
371
|
+
Geokit::Geocoders::GoogleGeocoder3.expects(:call_geocoder_service).with(url).returns(response)
|
372
|
+
res=Geokit::Geocoders::GoogleGeocoder3.geocode(@address)
|
373
|
+
assert_equal "CA", res.state
|
374
|
+
assert_equal "San Francisco", res.city
|
375
|
+
assert_equal "37.7921509,-122.394", res.ll # slightly dif from yahoo
|
376
|
+
assert res.is_us?
|
377
|
+
assert_equal "100 Spear St, San Francisco, CA 94105, USA", res.full_address #slightly different from yahoo
|
378
|
+
assert_equal "google3", res.provider
|
379
|
+
end
|
380
|
+
|
381
|
+
def test_google3_full_address_with_geo_loc
|
382
|
+
response = MockSuccess.new
|
383
|
+
response.expects(:body).returns(GOOGLE3_FULL)
|
384
|
+
url = "http://maps.google.com/maps/api/geocode/json?sensor=false&address=#{Geokit::Inflector::url_escape(@full_address_short_zip)}"
|
385
|
+
Geokit::Geocoders::GoogleGeocoder3.expects(:call_geocoder_service).with(url).returns(response)
|
386
|
+
res=Geokit::Geocoders::GoogleGeocoder3.geocode(@google_full_loc)
|
387
|
+
assert_equal "CA", res.state
|
388
|
+
assert_equal "San Francisco", res.city
|
389
|
+
assert_equal "37.7921509,-122.394", res.ll # slightly dif from yahoo
|
390
|
+
assert res.is_us?
|
391
|
+
assert_equal "100 Spear St, San Francisco, CA 94105, USA", res.full_address #slightly different from yahoo
|
392
|
+
assert_equal "google3", res.provider
|
393
|
+
end
|
394
|
+
|
395
|
+
def test_google3_full_address_accuracy
|
396
|
+
response = MockSuccess.new
|
397
|
+
response.expects(:body).returns(GOOGLE3_FULL)
|
398
|
+
url = "http://maps.google.com/maps/api/geocode/json?sensor=false&address=#{Geokit::Inflector::url_escape(@full_address_short_zip)}"
|
399
|
+
Geokit::Geocoders::GoogleGeocoder3.expects(:call_geocoder_service).with(url).returns(response)
|
400
|
+
res=Geokit::Geocoders::GoogleGeocoder3.geocode(@google_full_loc)
|
401
|
+
assert_equal 9, res.accuracy
|
402
|
+
end
|
403
|
+
|
404
|
+
def test_google3_city
|
405
|
+
response = MockSuccess.new
|
406
|
+
response.expects(:body).returns(GOOGLE3_CITY)
|
407
|
+
url = "http://maps.google.com/maps/api/geocode/json?sensor=false&address=#{Geokit::Inflector::url_escape(@address)}"
|
408
|
+
Geokit::Geocoders::GoogleGeocoder3.expects(:call_geocoder_service).with(url).returns(response)
|
409
|
+
res=Geokit::Geocoders::GoogleGeocoder3.do_geocode(@address)
|
410
|
+
assert_nil res.street_address
|
411
|
+
assert_equal "CA", res.state
|
412
|
+
assert_equal "San Francisco", res.city
|
413
|
+
assert_equal "37.7749295,-122.4194155", res.ll
|
414
|
+
assert res.is_us?
|
415
|
+
assert_equal "San Francisco, CA, USA", res.full_address
|
416
|
+
assert_equal "google3", res.provider
|
417
|
+
end
|
418
|
+
|
419
|
+
def test_google3_city_accuracy
|
420
|
+
response = MockSuccess.new
|
421
|
+
response.expects(:body).returns(GOOGLE3_CITY)
|
422
|
+
url = "http://maps.google.com/maps/api/geocode/json?sensor=false&address=#{Geokit::Inflector::url_escape(@address)}"
|
423
|
+
Geokit::Geocoders::GoogleGeocoder3.expects(:call_geocoder_service).with(url).returns(response)
|
424
|
+
res=Geokit::Geocoders::GoogleGeocoder3.geocode(@address)
|
425
|
+
assert_equal 4, res.accuracy
|
426
|
+
end
|
427
|
+
|
428
|
+
def test_google3_city_with_geo_loc
|
429
|
+
response = MockSuccess.new
|
430
|
+
response.expects(:body).returns(GOOGLE3_CITY)
|
431
|
+
url = "http://maps.google.com/maps/api/geocode/json?sensor=false&address=#{Geokit::Inflector::url_escape(@address)}"
|
432
|
+
Geokit::Geocoders::GoogleGeocoder3.expects(:call_geocoder_service).with(url).returns(response)
|
433
|
+
res=Geokit::Geocoders::GoogleGeocoder3.geocode(@google_city_loc)
|
434
|
+
assert_equal "CA", res.state
|
435
|
+
assert_equal "San Francisco", res.city
|
436
|
+
assert_equal "37.7749295,-122.4194155", res.ll
|
437
|
+
assert res.is_us?
|
438
|
+
assert_equal "San Francisco, CA, USA", res.full_address
|
439
|
+
assert_nil res.street_address
|
440
|
+
assert_equal "google3", res.provider
|
441
|
+
end
|
442
|
+
|
443
|
+
def test_google3_suggested_bounds
|
444
|
+
response = MockSuccess.new
|
445
|
+
response.expects(:body).returns(GOOGLE3_FULL)
|
446
|
+
url = "http://maps.google.com/maps/api/geocode/json?sensor=false&address=#{Geokit::Inflector::url_escape(@full_address_short_zip)}"
|
447
|
+
Geokit::Geocoders::GoogleGeocoder3.expects(:call_geocoder_service).with(url).returns(response)
|
448
|
+
res = Geokit::Geocoders::GoogleGeocoder3.geocode(@google_full_loc)
|
449
|
+
|
450
|
+
assert_instance_of Geokit::Bounds, res.suggested_bounds
|
451
|
+
assert_equal Geokit::Bounds.new(Geokit::LatLng.new(37.7890033, -122.3971476), Geokit::LatLng.new(37.7952985, -122.3908524)), res.suggested_bounds
|
452
|
+
end
|
453
|
+
|
454
|
+
def test_service_unavailable
|
455
|
+
response = MockFailure.new
|
456
|
+
url = "http://maps.google.com/maps/api/geocode/json?sensor=false&address=#{Geokit::Inflector::url_escape(@address)}"
|
457
|
+
Geokit::Geocoders::GoogleGeocoder3.expects(:call_geocoder_service).with(url).returns(response)
|
458
|
+
assert !Geokit::Geocoders::GoogleGeocoder3.geocode(@google_city_loc).success
|
459
|
+
end
|
460
|
+
|
461
|
+
def test_multiple_results
|
462
|
+
#Geokit::Geocoders::GoogleGeocoder3.do_geocode('via Sandro Pertini 8, Ossona, MI')
|
463
|
+
response = MockSuccess.new
|
464
|
+
response.expects(:body).returns(GOOGLE3_MULTI)
|
465
|
+
url = "http://maps.google.com/maps/api/geocode/json?sensor=false&address=#{Geokit::Inflector.url_escape('via Sandro Pertini 8, Ossona, MI')}"
|
466
|
+
Geokit::Geocoders::GoogleGeocoder3.expects(:call_geocoder_service).with(url).returns(response)
|
467
|
+
res=Geokit::Geocoders::GoogleGeocoder3.geocode('via Sandro Pertini 8, Ossona, MI')
|
468
|
+
assert_equal "Lombardy", res.state
|
469
|
+
assert_equal "Mesero", res.city
|
470
|
+
assert_equal "45.4966218,8.852694", res.ll
|
471
|
+
assert !res.is_us?
|
472
|
+
assert_equal "Via Sandro Pertini, 8, 20010 Mesero MI, Italy", res.full_address
|
473
|
+
assert_equal "8 Via Sandro Pertini", res.street_address
|
474
|
+
assert_equal "google3", res.provider
|
475
|
+
|
476
|
+
assert_equal 2, res.all.size
|
477
|
+
res = res.all[1]
|
478
|
+
assert_equal "Lombardy", res.state
|
479
|
+
assert_equal "Ossona", res.city
|
480
|
+
assert_equal "45.5074444,8.90232", res.ll
|
481
|
+
assert !res.is_us?
|
482
|
+
assert_equal "Via Sandro Pertini, 20010 Ossona MI, Italy", res.full_address
|
483
|
+
assert_equal "Via Sandro Pertini", res.street_address
|
484
|
+
assert_equal "google3", res.provider
|
485
|
+
end
|
486
|
+
#
|
487
|
+
def test_reverse_geocode
|
488
|
+
#Geokit::Geocoders::GoogleGeocoder3.do_reverse_geocode("40.4167413, -3.7032498")
|
489
|
+
madrid = Geokit::GeoLoc.new
|
490
|
+
madrid.lat, madrid.lng = "40.4167413", "-3.7032498"
|
491
|
+
response = MockSuccess.new
|
492
|
+
response.expects(:body).returns(GOOGLE3_REVERSE_MADRID)
|
493
|
+
url = "http://maps.google.com/maps/api/geocode/json?sensor=false&latlng=#{Geokit::Inflector::url_escape(madrid.ll)}"
|
494
|
+
Geokit::Geocoders::GoogleGeocoder3.expects(:call_geocoder_service).with(url).
|
495
|
+
returns(response)
|
496
|
+
res=Geokit::Geocoders::GoogleGeocoder3.do_reverse_geocode(madrid.ll)
|
497
|
+
|
498
|
+
assert_equal madrid.lat.to_s.slice(1..5), res.lat.to_s.slice(1..5)
|
499
|
+
assert_equal madrid.lng.to_s.slice(1..5), res.lng.to_s.slice(1..5)
|
500
|
+
assert_equal "ES", res.country_code
|
501
|
+
assert_equal "google3", res.provider
|
502
|
+
|
503
|
+
assert_equal "Madrid", res.city
|
504
|
+
assert_equal "Madrid", res.state
|
505
|
+
|
506
|
+
assert_equal "Spain", res.country
|
507
|
+
assert_equal "street", res.precision
|
508
|
+
assert_equal true, res.success
|
509
|
+
|
510
|
+
assert_equal "Calle de las Carretas, 28013 Madrid, Spain", res.full_address
|
511
|
+
assert_equal "28013", res.zip
|
512
|
+
assert_equal "Calle de las Carretas", res.street_address
|
513
|
+
end
|
514
|
+
|
515
|
+
def test_country_code_biasing
|
516
|
+
response = MockSuccess.new
|
517
|
+
response.expects(:body).returns(GOOGLE3_COUNTRY_CODE_BIASED_RESULT)
|
518
|
+
|
519
|
+
url = "http://maps.google.com/maps/api/geocode/json?sensor=false&address=Syracuse®ion=it"
|
520
|
+
Geokit::Geocoders::GoogleGeocoder3.expects(:call_geocoder_service).with(url).returns(response)
|
521
|
+
biased_result = Geokit::Geocoders::GoogleGeocoder3.geocode('Syracuse', :bias => 'it')
|
522
|
+
|
523
|
+
assert_equal 'IT', biased_result.country_code
|
524
|
+
assert_equal 'Sicily', biased_result.state
|
525
|
+
end
|
526
|
+
|
527
|
+
def test_too_many_queries
|
528
|
+
response = MockSuccess.new
|
529
|
+
response.expects(:body).returns(GOOGLE3_TOO_MANY)
|
530
|
+
url = "http://maps.google.com/maps/api/geocode/json?sensor=false&address=#{Geokit::Inflector.url_escape(@address)}"
|
531
|
+
Geokit::Geocoders::GoogleGeocoder3.expects(:call_geocoder_service).with(url).returns(response)
|
532
|
+
assert_raise Geokit::TooManyQueriesError do
|
533
|
+
res=Geokit::Geocoders::GoogleGeocoder3.geocode(@address)
|
534
|
+
end
|
535
|
+
end
|
536
|
+
end
|
data/test/test_ipgeocoder.rb
CHANGED
@@ -4,8 +4,8 @@ require File.join(File.dirname(__FILE__), 'test_base_geocoder')
|
|
4
4
|
class IpGeocoderTest < BaseGeocoderTest #:nodoc: all
|
5
5
|
|
6
6
|
IP_FAILURE=<<-EOF
|
7
|
-
Country:
|
8
|
-
City: (
|
7
|
+
Country: SWITZERLAND (CH)
|
8
|
+
City: (Unknown City)
|
9
9
|
Latitude:
|
10
10
|
Longitude:
|
11
11
|
EOF
|
@@ -24,10 +24,22 @@ class IpGeocoderTest < BaseGeocoderTest #:nodoc: all
|
|
24
24
|
Longitude: 12.9167
|
25
25
|
EOF
|
26
26
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
27
|
+
PRIVATE_IPS_TO_TEST = [
|
28
|
+
'10.10.10.10',
|
29
|
+
'172.16.1.3',
|
30
|
+
'172.22.3.42',
|
31
|
+
'172.30.254.164',
|
32
|
+
'192.168.1.1',
|
33
|
+
'0.0.0.0',
|
34
|
+
'127.0.0.1',
|
35
|
+
'240.3.4.5',
|
36
|
+
'225.1.6.55'
|
37
|
+
].freeze
|
38
|
+
|
39
|
+
def setup
|
40
|
+
super
|
41
|
+
@success.provider = "hostip"
|
42
|
+
end
|
31
43
|
|
32
44
|
def test_successful_lookup
|
33
45
|
success = MockSuccess.new
|
@@ -64,14 +76,24 @@ class IpGeocoderTest < BaseGeocoderTest #:nodoc: all
|
|
64
76
|
def test_failed_lookup
|
65
77
|
failure = MockSuccess.new
|
66
78
|
failure.expects(:body).returns(IP_FAILURE)
|
67
|
-
url = 'http://api.hostip.info/get_html.php?ip=
|
79
|
+
url = 'http://api.hostip.info/get_html.php?ip=128.178.0.0&position=true'
|
68
80
|
GeoKit::Geocoders::IpGeocoder.expects(:call_geocoder_service).with(url).returns(failure)
|
69
|
-
location = GeoKit::Geocoders::IpGeocoder.geocode("
|
81
|
+
location = GeoKit::Geocoders::IpGeocoder.geocode("128.178.0.0")
|
70
82
|
assert_not_nil location
|
71
83
|
assert !location.success?
|
72
84
|
end
|
73
85
|
|
86
|
+
def test_private_ips
|
87
|
+
GeoKit::Geocoders::IpGeocoder.expects(:call_geocoder_service).never
|
88
|
+
PRIVATE_IPS_TO_TEST.each do |ip|
|
89
|
+
location = GeoKit::Geocoders::IpGeocoder.geocode(ip)
|
90
|
+
assert_not_nil location
|
91
|
+
assert !location.success?
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
74
95
|
def test_invalid_ip
|
96
|
+
GeoKit::Geocoders::IpGeocoder.expects(:call_geocoder_service).never
|
75
97
|
location = GeoKit::Geocoders::IpGeocoder.geocode("blah")
|
76
98
|
assert_not_nil location
|
77
99
|
assert !location.success?
|
@@ -79,9 +101,9 @@ class IpGeocoderTest < BaseGeocoderTest #:nodoc: all
|
|
79
101
|
|
80
102
|
def test_service_unavailable
|
81
103
|
failure = MockFailure.new
|
82
|
-
url = 'http://api.hostip.info/get_html.php?ip=
|
104
|
+
url = 'http://api.hostip.info/get_html.php?ip=12.215.42.19&position=true'
|
83
105
|
GeoKit::Geocoders::IpGeocoder.expects(:call_geocoder_service).with(url).returns(failure)
|
84
|
-
location = GeoKit::Geocoders::IpGeocoder.geocode("
|
106
|
+
location = GeoKit::Geocoders::IpGeocoder.geocode("12.215.42.19")
|
85
107
|
assert_not_nil location
|
86
108
|
assert !location.success?
|
87
109
|
end
|
data/test/test_yahoo_geocoder.rb
CHANGED
@@ -4,15 +4,15 @@ Geokit::Geocoders::yahoo = 'Yahoo'
|
|
4
4
|
|
5
5
|
class YahooGeocoderTest < BaseGeocoderTest #:nodoc: all
|
6
6
|
YAHOO_FULL=<<-EOF.strip
|
7
|
-
|
8
|
-
|
9
|
-
|
7
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
8
|
+
<ResultSet version="1.0"><Error>0</Error><ErrorMessage>No error</ErrorMessage><Locale>us_US</Locale><Quality>87</Quality><Found>1</Found><Result><quality>87</quality><latitude>37.792418</latitude><longitude>-122.393913</longitude><offsetlat>37.792332</offsetlat><offsetlon>-122.394027</offsetlon><radius>500</radius><name></name><line1>100 Spear St</line1><line2>San Francisco, CA 94105-1578</line2><line3></line3><line4>United States</line4><house>100</house><street>Spear St</street><xstreet></xstreet><unittype></unittype><unit></unit><postal>94105-1578</postal><neighborhood></neighborhood><city>San Francisco</city><county>San Francisco County</county><state>California</state><country>United States</country><countrycode>US</countrycode><statecode>CA</statecode><countycode></countycode><uzip>94105</uzip><hash>0FA06819B5F53E75</hash><woeid>12797156</woeid><woetype>11</woetype></Result></ResultSet>
|
9
|
+
<!-- gws17.maps.sp1.yahoo.com uncompressed/chunked Fri Feb 11 13:41:03 PST 2011 -->
|
10
10
|
EOF
|
11
11
|
|
12
12
|
YAHOO_CITY=<<-EOF.strip
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
14
|
+
<ResultSet version="1.0"><Error>0</Error><ErrorMessage>No error</ErrorMessage><Locale>us_US</Locale><Quality>40</Quality><Found>1</Found><Result><quality>40</quality><latitude>37.777125</latitude><longitude>-122.419644</longitude><offsetlat>37.777125</offsetlat><offsetlon>-122.419644</offsetlon><radius>10700</radius><name></name><line1></line1><line2>San Francisco, CA</line2><line3></line3><line4>United States</line4><house></house><street></street><xstreet></xstreet><unittype></unittype><unit></unit><postal></postal><neighborhood></neighborhood><city>San Francisco</city><county>San Francisco County</county><state>California</state><country>United States</country><countrycode>US</countrycode><statecode>CA</statecode><countycode></countycode><uzip>94102</uzip><hash></hash><woeid>2487956</woeid><woetype>7</woetype></Result></ResultSet>
|
15
|
+
<!-- gws31.maps.sp1.yahoo.com uncompressed/chunked Fri Feb 11 13:38:19 PST 2011 -->
|
16
16
|
EOF
|
17
17
|
|
18
18
|
def setup
|
@@ -27,7 +27,7 @@ class YahooGeocoderTest < BaseGeocoderTest #:nodoc: all
|
|
27
27
|
def test_yahoo_full_address
|
28
28
|
response = MockSuccess.new
|
29
29
|
response.expects(:body).returns(YAHOO_FULL)
|
30
|
-
url = "http://
|
30
|
+
url = "http://where.yahooapis.com/geocode?appid=Yahoo&count=100&location=#{Geokit::Inflector.url_escape(@address)}"
|
31
31
|
Geokit::Geocoders::YahooGeocoder.expects(:call_geocoder_service).with(url).returns(response)
|
32
32
|
do_full_address_assertions(Geokit::Geocoders::YahooGeocoder.geocode(@address))
|
33
33
|
end
|
@@ -35,16 +35,25 @@ class YahooGeocoderTest < BaseGeocoderTest #:nodoc: all
|
|
35
35
|
def test_yahoo_full_address_accuracy
|
36
36
|
response = MockSuccess.new
|
37
37
|
response.expects(:body).returns(YAHOO_FULL)
|
38
|
-
url = "http://
|
38
|
+
url = "http://where.yahooapis.com/geocode?appid=Yahoo&count=100&location=#{Geokit::Inflector.url_escape(@address)}"
|
39
39
|
Geokit::Geocoders::YahooGeocoder.expects(:call_geocoder_service).with(url).returns(response)
|
40
40
|
res = Geokit::Geocoders::YahooGeocoder.geocode(@address)
|
41
41
|
assert_equal 8, res.accuracy
|
42
42
|
end
|
43
43
|
|
44
|
+
def test_yahoo_full_address_precision
|
45
|
+
response = MockSuccess.new
|
46
|
+
response.expects(:body).returns(YAHOO_FULL)
|
47
|
+
url = "http://where.yahooapis.com/geocode?appid=Yahoo&count=100&location=#{Geokit::Inflector.url_escape(@address)}"
|
48
|
+
Geokit::Geocoders::YahooGeocoder.expects(:call_geocoder_service).with(url).returns(response)
|
49
|
+
res = Geokit::Geocoders::YahooGeocoder.geocode(@address)
|
50
|
+
assert_equal 'address', res.precision
|
51
|
+
end
|
52
|
+
|
44
53
|
def test_yahoo_full_address_with_geo_loc
|
45
54
|
response = MockSuccess.new
|
46
55
|
response.expects(:body).returns(YAHOO_FULL)
|
47
|
-
url = "http://
|
56
|
+
url = "http://where.yahooapis.com/geocode?appid=Yahoo&count=100&location=#{Geokit::Inflector.url_escape(@full_address)}"
|
48
57
|
Geokit::Geocoders::YahooGeocoder.expects(:call_geocoder_service).with(url).returns(response)
|
49
58
|
do_full_address_assertions(Geokit::Geocoders::YahooGeocoder.geocode(@yahoo_full_loc))
|
50
59
|
end
|
@@ -52,7 +61,7 @@ class YahooGeocoderTest < BaseGeocoderTest #:nodoc: all
|
|
52
61
|
def test_yahoo_city
|
53
62
|
response = MockSuccess.new
|
54
63
|
response.expects(:body).returns(YAHOO_CITY)
|
55
|
-
url = "http://
|
64
|
+
url = "http://where.yahooapis.com/geocode?appid=Yahoo&count=100&location=#{Geokit::Inflector.url_escape(@address)}"
|
56
65
|
Geokit::Geocoders::YahooGeocoder.expects(:call_geocoder_service).with(url).returns(response)
|
57
66
|
do_city_assertions(Geokit::Geocoders::YahooGeocoder.geocode(@address))
|
58
67
|
end
|
@@ -60,23 +69,32 @@ class YahooGeocoderTest < BaseGeocoderTest #:nodoc: all
|
|
60
69
|
def test_yahoo_city_accuracy
|
61
70
|
response = MockSuccess.new
|
62
71
|
response.expects(:body).returns(YAHOO_CITY)
|
63
|
-
url = "http://
|
72
|
+
url = "http://where.yahooapis.com/geocode?appid=Yahoo&count=100&location=#{Geokit::Inflector.url_escape(@address)}"
|
64
73
|
Geokit::Geocoders::YahooGeocoder.expects(:call_geocoder_service).with(url).returns(response)
|
65
74
|
res = Geokit::Geocoders::YahooGeocoder.geocode(@address)
|
66
75
|
assert_equal 4, res.accuracy
|
67
76
|
end
|
68
77
|
|
78
|
+
def test_yahoo_city_precision
|
79
|
+
response = MockSuccess.new
|
80
|
+
response.expects(:body).returns(YAHOO_CITY)
|
81
|
+
url = "http://where.yahooapis.com/geocode?appid=Yahoo&count=100&location=#{Geokit::Inflector.url_escape(@address)}"
|
82
|
+
Geokit::Geocoders::YahooGeocoder.expects(:call_geocoder_service).with(url).returns(response)
|
83
|
+
res = Geokit::Geocoders::YahooGeocoder.geocode(@address)
|
84
|
+
assert_equal 'city', res.precision
|
85
|
+
end
|
86
|
+
|
69
87
|
def test_yahoo_city_with_geo_loc
|
70
88
|
response = MockSuccess.new
|
71
89
|
response.expects(:body).returns(YAHOO_CITY)
|
72
|
-
url = "http://
|
90
|
+
url = "http://where.yahooapis.com/geocode?appid=Yahoo&count=100&location=#{Geokit::Inflector.url_escape(@address)}"
|
73
91
|
Geokit::Geocoders::YahooGeocoder.expects(:call_geocoder_service).with(url).returns(response)
|
74
92
|
do_city_assertions(Geokit::Geocoders::YahooGeocoder.geocode(@yahoo_city_loc))
|
75
93
|
end
|
76
94
|
|
77
95
|
def test_service_unavailable
|
78
96
|
response = MockFailure.new
|
79
|
-
url = "http://
|
97
|
+
url = "http://where.yahooapis.com/geocode?appid=Yahoo&count=100&location=#{Geokit::Inflector.url_escape(@address)}"
|
80
98
|
Geokit::Geocoders::YahooGeocoder.expects(:call_geocoder_service).with(url).returns(response)
|
81
99
|
assert !Geokit::Geocoders::YahooGeocoder.geocode(@yahoo_city_loc).success
|
82
100
|
end
|
@@ -87,16 +105,16 @@ class YahooGeocoderTest < BaseGeocoderTest #:nodoc: all
|
|
87
105
|
def do_full_address_assertions(res)
|
88
106
|
assert_equal "CA", res.state
|
89
107
|
assert_equal "San Francisco", res.city
|
90
|
-
assert_equal "37.
|
108
|
+
assert_equal "37.792418,-122.393913", res.ll
|
91
109
|
assert res.is_us?
|
92
|
-
assert_equal "100 Spear St, San Francisco, CA
|
110
|
+
assert_equal "100 Spear St, San Francisco, CA 94105-1578", res.full_address
|
93
111
|
assert_equal "yahoo", res.provider
|
94
112
|
end
|
95
113
|
|
96
114
|
def do_city_assertions(res)
|
97
115
|
assert_equal "CA", res.state
|
98
116
|
assert_equal "San Francisco", res.city
|
99
|
-
assert_equal "37.
|
117
|
+
assert_equal "37.777125,-122.419644", res.ll
|
100
118
|
assert res.is_us?
|
101
119
|
assert_equal "San Francisco, CA, US", res.full_address
|
102
120
|
assert_nil res.street_address
|
metadata
CHANGED
@@ -5,9 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 1
|
7
7
|
- 5
|
8
|
-
-
|
9
|
-
|
10
|
-
version: 1.5.0.2
|
8
|
+
- 1
|
9
|
+
version: 1.5.1
|
11
10
|
platform: ruby
|
12
11
|
authors:
|
13
12
|
- Andre Lewis and Bill Eisenhauer
|
@@ -17,8 +16,19 @@ cert_chain: []
|
|
17
16
|
|
18
17
|
date: 2009-08-02 00:00:00 -07:00
|
19
18
|
default_executable:
|
20
|
-
dependencies:
|
21
|
-
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: json_pure
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
segments:
|
28
|
+
- 0
|
29
|
+
version: "0"
|
30
|
+
type: :runtime
|
31
|
+
version_requirements: *id001
|
22
32
|
description: Geokit Gem
|
23
33
|
email:
|
24
34
|
- andre@earthcode.com / bill_eisenhauer@yahoo.com
|
@@ -40,6 +50,7 @@ files:
|
|
40
50
|
- test/test_bounds.rb
|
41
51
|
- test/test_ca_geocoder.rb
|
42
52
|
- test/test_geoloc.rb
|
53
|
+
- test/test_google_geocoder3.rb
|
43
54
|
- test/test_google_geocoder.rb
|
44
55
|
- test/test_latlng.rb
|
45
56
|
- test/test_multi_geocoder.rb
|
@@ -82,6 +93,7 @@ test_files:
|
|
82
93
|
- test/test_ca_geocoder.rb
|
83
94
|
- test/test_geoloc.rb
|
84
95
|
- test/test_geoplugin_geocoder.rb
|
96
|
+
- test/test_google_geocoder3.rb
|
85
97
|
- test/test_google_geocoder.rb
|
86
98
|
- test/test_google_reverse_geocoder.rb
|
87
99
|
- test/test_inflector.rb
|