geocoder 0.9.13 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of geocoder might be problematic. Click here for more details.
- data/CHANGELOG.rdoc +16 -7
- data/README.rdoc +116 -51
- data/bin/geocode +5 -0
- data/lib/geocoder.rb +30 -43
- data/lib/geocoder/calculations.rb +4 -21
- data/lib/geocoder/cli.rb +111 -0
- data/lib/geocoder/configuration.rb +6 -7
- data/lib/geocoder/lookups/base.rb +36 -9
- data/lib/geocoder/lookups/bing.rb +33 -0
- data/lib/geocoder/lookups/google.rb +4 -0
- data/lib/geocoder/lookups/yahoo.rb +5 -2
- data/lib/geocoder/lookups/yandex.rb +39 -0
- data/lib/geocoder/models/base.rb +5 -1
- data/lib/geocoder/results/base.rb +16 -0
- data/lib/geocoder/results/bing.rb +48 -0
- data/lib/geocoder/results/freegeoip.rb +10 -3
- data/lib/geocoder/results/geocoder_ca.rb +14 -12
- data/lib/geocoder/results/google.rb +15 -2
- data/lib/geocoder/results/yahoo.rb +10 -2
- data/lib/geocoder/results/yandex.rb +48 -0
- data/lib/geocoder/stores/active_record.rb +2 -7
- data/lib/geocoder/stores/base.rb +2 -10
- data/lib/geocoder/version.rb +3 -0
- data/test/fixtures/bing_madison_square_garden.json +40 -0
- data/test/fixtures/bing_no_results.json +16 -0
- data/test/fixtures/bing_reverse.json +42 -0
- data/test/fixtures/yandex_invalid_key.json +1 -0
- data/test/fixtures/yandex_kremlin.json +48 -0
- data/test/fixtures/yandex_no_results.json +16 -0
- data/test/geocoder_test.rb +58 -8
- data/test/test_helper.rb +39 -3
- metadata +69 -58
- data/VERSION +0 -1
- data/lib/geocoder/stores/active_record_legacy.rb +0 -62
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'geocoder/results/base'
|
2
|
+
|
3
|
+
module Geocoder::Result
|
4
|
+
class Yandex < Base
|
5
|
+
|
6
|
+
def coordinates
|
7
|
+
@data['GeoObject']['Point']['pos'].split(' ').reverse.map(&:to_f)
|
8
|
+
end
|
9
|
+
|
10
|
+
def address(format = :full)
|
11
|
+
@data['GeoObject']['metaDataProperty']['GeocoderMetaData']['text']
|
12
|
+
end
|
13
|
+
|
14
|
+
def city
|
15
|
+
address_details['Locality']['LocalityName']
|
16
|
+
end
|
17
|
+
|
18
|
+
def country
|
19
|
+
address_details['CountryName']
|
20
|
+
end
|
21
|
+
|
22
|
+
def country_code
|
23
|
+
address_details['CountryNameCode']
|
24
|
+
end
|
25
|
+
|
26
|
+
def state
|
27
|
+
""
|
28
|
+
end
|
29
|
+
|
30
|
+
def state_code
|
31
|
+
""
|
32
|
+
end
|
33
|
+
|
34
|
+
def postal_code
|
35
|
+
""
|
36
|
+
end
|
37
|
+
|
38
|
+
def premise_name
|
39
|
+
address_details['Locality']['Premise']['PremiseName']
|
40
|
+
end
|
41
|
+
|
42
|
+
private # ----------------------------------------------------------------
|
43
|
+
|
44
|
+
def address_details
|
45
|
+
@data['GeoObject']['metaDataProperty']['GeocoderMetaData']['AddressDetails']['Country']
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'geocoder/stores/base'
|
2
|
-
require 'geocoder/stores/active_record_legacy'
|
3
2
|
|
4
3
|
##
|
5
4
|
# Add geocoding functionality to any ActiveRecord object.
|
@@ -7,7 +6,6 @@ require 'geocoder/stores/active_record_legacy'
|
|
7
6
|
module Geocoder::Store
|
8
7
|
module ActiveRecord
|
9
8
|
include Base
|
10
|
-
include ActiveRecord::Legacy
|
11
9
|
|
12
10
|
##
|
13
11
|
# Implementation of 'included' hook method.
|
@@ -180,9 +178,6 @@ module Geocoder::Store
|
|
180
178
|
conditions[0] << " AND #{table_name}.id != ?"
|
181
179
|
conditions << obj.id
|
182
180
|
end
|
183
|
-
if options[:limit] || options[:offset]
|
184
|
-
warn "DEPRECATION WARNING: The :limit and :offset options to Geocoder's 'near' method are deprecated and will be removed in Geocoder v1.0. Please specify these options using ARel relations instead, for example: Place.near(...).limit(10).offset(20)."
|
185
|
-
end
|
186
181
|
{
|
187
182
|
:group => columns.map{ |c| "#{table_name}.#{c.name}" }.join(','),
|
188
183
|
:order => options[:order],
|
@@ -208,7 +203,7 @@ module Geocoder::Store
|
|
208
203
|
end
|
209
204
|
end
|
210
205
|
|
211
|
-
|
206
|
+
alias_method :fetch_coordinates, :geocode
|
212
207
|
|
213
208
|
##
|
214
209
|
# Look up address and assign to +address+ attribute (or other as specified
|
@@ -224,6 +219,6 @@ module Geocoder::Store
|
|
224
219
|
end
|
225
220
|
end
|
226
221
|
|
227
|
-
|
222
|
+
alias_method :fetch_address, :reverse_geocode
|
228
223
|
end
|
229
224
|
end
|
data/lib/geocoder/stores/base.rb
CHANGED
@@ -22,14 +22,10 @@ module Geocoder
|
|
22
22
|
# the point. Also takes a symbol specifying the units
|
23
23
|
# (:mi or :km; default is :mi).
|
24
24
|
#
|
25
|
-
def distance_to(point,
|
26
|
-
if point.is_a?(Numeric) and args[0].is_a?(Numeric)
|
27
|
-
warn "DEPRECATION WARNING: Instead of passing latitude/longitude as separate arguments to the distance_to/from method, please pass an array [#{point},#{args[0]}], a geocoded object, or a geocodable address (string). The old argument format will not be supported in Geocoder v.1.0."
|
28
|
-
point = [point, args.shift]
|
29
|
-
end
|
25
|
+
def distance_to(point, units = :mi)
|
30
26
|
return nil unless geocoded?
|
31
27
|
Geocoder::Calculations.distance_between(
|
32
|
-
to_coordinates, point, :units =>
|
28
|
+
to_coordinates, point, :units => units)
|
33
29
|
end
|
34
30
|
|
35
31
|
alias_method :distance_from, :distance_to
|
@@ -62,10 +58,6 @@ module Geocoder
|
|
62
58
|
#
|
63
59
|
def nearbys(radius = 20, options = {})
|
64
60
|
return [] unless geocoded?
|
65
|
-
if options.is_a?(Symbol)
|
66
|
-
options = {:units => options}
|
67
|
-
warn "DEPRECATION WARNING: The units argument to the nearbys method has been replaced with an options hash (same options hash as the near scope). You should instead call: obj.nearbys(#{radius}, :units => #{options[:units]}). The old syntax will not be supported in Geocoder v1.0."
|
68
|
-
end
|
69
61
|
options.merge!(:exclude => self)
|
70
62
|
self.class.near(self, radius, options)
|
71
63
|
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
{
|
2
|
+
"authenticationResultCode":"ValidCredentials",
|
3
|
+
"brandLogoUri":"http:\/\/dev.virtualearth.net\/Branding\/logo_powered_by.png",
|
4
|
+
"copyright":"Copyright © 2011 Microsoft and its suppliers. All rights reserved. This API cannot be accessed and the content and any results may not be used, reproduced or transmitted in any manner without express written permission from Microsoft Corporation.",
|
5
|
+
"resourceSets":[
|
6
|
+
{
|
7
|
+
"estimatedTotal":1,
|
8
|
+
"resources":[
|
9
|
+
{
|
10
|
+
"__type":"Location:http:\/\/schemas.microsoft.com\/search\/local\/ws\/rest\/v1",
|
11
|
+
"bbox":[
|
12
|
+
40.744944289326668,
|
13
|
+
-74.002353921532631,
|
14
|
+
40.755675807595253,
|
15
|
+
-73.983625397086143
|
16
|
+
],
|
17
|
+
"name":"Madison Square Garden, NY",
|
18
|
+
"point":{
|
19
|
+
"type":"Point",
|
20
|
+
"coordinates":[
|
21
|
+
40.75031,
|
22
|
+
-73.99299
|
23
|
+
]
|
24
|
+
},
|
25
|
+
"address":{
|
26
|
+
"adminDistrict":"NY",
|
27
|
+
"countryRegion":"United States",
|
28
|
+
"formattedAddress":"Madison Square Garden, NY",
|
29
|
+
"locality":"New York"
|
30
|
+
},
|
31
|
+
"confidence":"High",
|
32
|
+
"entityType":"Stadium"
|
33
|
+
}
|
34
|
+
]
|
35
|
+
}
|
36
|
+
],
|
37
|
+
"statusCode":200,
|
38
|
+
"statusDescription":"OK",
|
39
|
+
"traceId":"55094ee53c8d45e789794014666328cd|CH1M001466|02.00.82.2800|CH1MSNVM001396, CH1MSNVM001370, CH1MSNVM001397"
|
40
|
+
}
|
@@ -0,0 +1,16 @@
|
|
1
|
+
{
|
2
|
+
"authenticationResultCode":"ValidCredentials",
|
3
|
+
"brandLogoUri":"http:\/\/dev.virtualearth.net\/Branding\/logo_powered_by.png",
|
4
|
+
"copyright":"Copyright © 2011 Microsoft and its suppliers. All rights reserved. This API cannot be accessed and the content and any results may not be used, reproduced or transmitted in any manner without express written permission from Microsoft Corporation.",
|
5
|
+
"resourceSets":[
|
6
|
+
{
|
7
|
+
"estimatedTotal":0,
|
8
|
+
"resources":[
|
9
|
+
|
10
|
+
]
|
11
|
+
}
|
12
|
+
],
|
13
|
+
"statusCode":200,
|
14
|
+
"statusDescription":"OK",
|
15
|
+
"traceId":"907b76a307bc49129a489de3d4c992ea|CH1M001463|02.00.82.2800|CH1MSNVM001383, CH1MSNVM001358, CH1MSNVM001397"
|
16
|
+
}
|
@@ -0,0 +1,42 @@
|
|
1
|
+
{
|
2
|
+
"authenticationResultCode":"ValidCredentials",
|
3
|
+
"brandLogoUri":"http:\/\/dev.virtualearth.net\/Branding\/logo_powered_by.png",
|
4
|
+
"copyright":"Copyright © 2011 Microsoft and its suppliers. All rights reserved. This API cannot be accessed and the content and any results may not be used, reproduced or transmitted in any manner without express written permission from Microsoft Corporation.",
|
5
|
+
"resourceSets":[
|
6
|
+
{
|
7
|
+
"estimatedTotal":1,
|
8
|
+
"resources":[
|
9
|
+
{
|
10
|
+
"__type":"Location:http:\/\/schemas.microsoft.com\/search\/local\/ws\/rest\/v1",
|
11
|
+
"bbox":[
|
12
|
+
45.419835111675845,
|
13
|
+
-75.683656128790716,
|
14
|
+
45.4275605468172,
|
15
|
+
-75.66898098334994
|
16
|
+
],
|
17
|
+
"name":"291 Rue Somerset E, Ottawa, ON, K1N",
|
18
|
+
"point":{
|
19
|
+
"type":"Point",
|
20
|
+
"coordinates":[
|
21
|
+
45.423697829246521,
|
22
|
+
-75.676318556070328
|
23
|
+
]
|
24
|
+
},
|
25
|
+
"address":{
|
26
|
+
"addressLine":"291 Rue Somerset E",
|
27
|
+
"adminDistrict":"ON",
|
28
|
+
"countryRegion":"Canada",
|
29
|
+
"formattedAddress":"291 Rue Somerset E, Ottawa, ON, K1N",
|
30
|
+
"locality":"Ottawa",
|
31
|
+
"postalCode":"K1N"
|
32
|
+
},
|
33
|
+
"confidence":"Medium",
|
34
|
+
"entityType":"Address"
|
35
|
+
}
|
36
|
+
]
|
37
|
+
}
|
38
|
+
],
|
39
|
+
"statusCode":200,
|
40
|
+
"statusDescription":"OK",
|
41
|
+
"traceId":"27bd5ed659e64ba6970c4144f1d4ea94|CH1M001470|02.00.82.2800|CH1MSNVM001396, CH1MSNVM001374"
|
42
|
+
}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"error":{"status":401,"message":"invalid key"}}
|
@@ -0,0 +1,48 @@
|
|
1
|
+
{
|
2
|
+
"response": {
|
3
|
+
"GeoObjectCollection": {
|
4
|
+
"metaDataProperty": {
|
5
|
+
"GeocoderResponseMetaData": {
|
6
|
+
"request": "Кремль, Moscow, Russia",
|
7
|
+
"found": "1",
|
8
|
+
"results": "10"
|
9
|
+
}
|
10
|
+
},
|
11
|
+
"featureMember": [
|
12
|
+
{
|
13
|
+
"GeoObject": {
|
14
|
+
"metaDataProperty": {
|
15
|
+
"GeocoderMetaData": {
|
16
|
+
"kind": "vegetation",
|
17
|
+
"text": "Россия, Москва, Московский Кремль",
|
18
|
+
"precision": "other",
|
19
|
+
"AddressDetails": {
|
20
|
+
"Country": {
|
21
|
+
"CountryNameCode": "RU",
|
22
|
+
"CountryName": "Россия",
|
23
|
+
"Locality": {
|
24
|
+
"LocalityName": "Москва",
|
25
|
+
"Premise": {
|
26
|
+
"PremiseName": "Московский Кремль"
|
27
|
+
}
|
28
|
+
}
|
29
|
+
}
|
30
|
+
}
|
31
|
+
}
|
32
|
+
},
|
33
|
+
"name": "Московский Кремль",
|
34
|
+
"boundedBy": {
|
35
|
+
"Envelope": {
|
36
|
+
"lowerCorner": "37.584182 55.733361",
|
37
|
+
"upperCorner": "37.650064 55.770517"
|
38
|
+
}
|
39
|
+
},
|
40
|
+
"Point": {
|
41
|
+
"pos": "37.617123 55.751943"
|
42
|
+
}
|
43
|
+
}
|
44
|
+
}
|
45
|
+
]
|
46
|
+
}
|
47
|
+
}
|
48
|
+
}
|
data/test/geocoder_test.rb
CHANGED
@@ -20,6 +20,24 @@ class GeocoderTest < Test::Unit::TestCase
|
|
20
20
|
|
21
21
|
# --- sanity checks ---
|
22
22
|
|
23
|
+
def test_uses_proxy_when_specified
|
24
|
+
Geocoder::Configuration.http_proxy = 'localhost'
|
25
|
+
lookup = Geocoder::Lookup::Google.new
|
26
|
+
assert lookup.send(:http_client).proxy_class?
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_doesnt_use_proxy_when_not_specified
|
30
|
+
lookup = Geocoder::Lookup::Google.new
|
31
|
+
assert !lookup.send(:http_client).proxy_class?
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_exception_raised_on_bad_proxy_url
|
35
|
+
Geocoder::Configuration.http_proxy = ' \\_O< Quack Quack'
|
36
|
+
assert_raise Geocoder::ConfigurationError do
|
37
|
+
Geocoder::Lookup::Google.new.send(:http_client)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
23
41
|
def test_uses_https_for_secure_query
|
24
42
|
Geocoder::Configuration.use_https = true
|
25
43
|
g = Geocoder::Lookup::Google.new
|
@@ -369,6 +387,17 @@ class GeocoderTest < Test::Unit::TestCase
|
|
369
387
|
end
|
370
388
|
|
371
389
|
|
390
|
+
# --- Yandex ---
|
391
|
+
|
392
|
+
def test_yandex_with_invalid_key
|
393
|
+
# keep test output clean: suppress timeout warning
|
394
|
+
orig = $VERBOSE; $VERBOSE = nil
|
395
|
+
Geocoder::Configuration.lookup = :yandex
|
396
|
+
assert_equal [], Geocoder.search("invalid key")
|
397
|
+
$VERBOSE = orig
|
398
|
+
end
|
399
|
+
|
400
|
+
|
372
401
|
# --- Geocoder.ca ---
|
373
402
|
|
374
403
|
def test_geocoder_ca_result_components
|
@@ -392,6 +421,23 @@ class GeocoderTest < Test::Unit::TestCase
|
|
392
421
|
end
|
393
422
|
|
394
423
|
|
424
|
+
# --- Bing ---
|
425
|
+
|
426
|
+
def test_bing_result_components
|
427
|
+
Geocoder::Configuration.lookup = :bing
|
428
|
+
result = Geocoder.search("Madison Square Garden, New York, NY").first
|
429
|
+
assert_equal "Madison Square Garden, NY", result.address
|
430
|
+
assert_equal "NY", result.state
|
431
|
+
assert_equal "New York", result.city
|
432
|
+
end
|
433
|
+
|
434
|
+
def test_bing_no_results
|
435
|
+
Geocoder::Configuration.lookup = :bing
|
436
|
+
results = Geocoder.search("no results")
|
437
|
+
assert_equal 0, results.length
|
438
|
+
end
|
439
|
+
|
440
|
+
|
395
441
|
# --- search queries ---
|
396
442
|
|
397
443
|
def test_hash_to_query
|
@@ -416,13 +462,17 @@ class GeocoderTest < Test::Unit::TestCase
|
|
416
462
|
|
417
463
|
def assert_result_has_required_attributes(result)
|
418
464
|
m = "Lookup #{Geocoder::Configuration.lookup} does not support %s attribute."
|
419
|
-
assert result.coordinates.is_a?(Array),
|
420
|
-
assert result.latitude.is_a?(Float),
|
421
|
-
assert result.longitude.is_a?(Float),
|
422
|
-
assert result.city.is_a?(String),
|
423
|
-
assert result.
|
424
|
-
assert result.
|
425
|
-
assert result.
|
426
|
-
|
465
|
+
assert result.coordinates.is_a?(Array), m % "coordinates"
|
466
|
+
assert result.latitude.is_a?(Float), m % "latitude"
|
467
|
+
assert result.longitude.is_a?(Float), m % "longitude"
|
468
|
+
assert result.city.is_a?(String), m % "city"
|
469
|
+
assert result.state.is_a?(String), m % "state"
|
470
|
+
assert result.state_code.is_a?(String), m % "state_code"
|
471
|
+
assert result.province.is_a?(String), m % "province"
|
472
|
+
assert result.province_code.is_a?(String), m % "province_code"
|
473
|
+
assert result.postal_code.is_a?(String), m % "postal_code"
|
474
|
+
assert result.country.is_a?(String), m % "country"
|
475
|
+
assert result.country_code.is_a?(String), m % "country_code"
|
476
|
+
assert_not_nil result.address, m % "address"
|
427
477
|
end
|
428
478
|
end
|
data/test/test_helper.rb
CHANGED
@@ -75,11 +75,27 @@ module Geocoder
|
|
75
75
|
private #-----------------------------------------------------------------
|
76
76
|
def fetch_raw_data(query, reverse = false)
|
77
77
|
raise TimeoutError if query == "timeout"
|
78
|
-
file = query
|
78
|
+
file = case query
|
79
|
+
when "no results"; :no_results
|
80
|
+
else :madison_square_garden
|
81
|
+
end
|
79
82
|
read_fixture "yahoo_#{file}.json"
|
80
83
|
end
|
81
84
|
end
|
82
85
|
|
86
|
+
class Yandex < Base
|
87
|
+
private #-----------------------------------------------------------------
|
88
|
+
def fetch_raw_data(query, reverse = false)
|
89
|
+
raise TimeoutError if query == "timeout"
|
90
|
+
file = case query
|
91
|
+
when "no results"; :no_results
|
92
|
+
when "invalid key"; :invalid_key
|
93
|
+
else :kremlin
|
94
|
+
end
|
95
|
+
read_fixture "yandex_#{file}.json"
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
83
99
|
class GeocoderCa < Base
|
84
100
|
private #-----------------------------------------------------------------
|
85
101
|
def fetch_raw_data(query, reverse = false)
|
@@ -87,7 +103,10 @@ module Geocoder
|
|
87
103
|
if reverse
|
88
104
|
read_fixture "geocoder_ca_reverse.json"
|
89
105
|
else
|
90
|
-
file = query
|
106
|
+
file = case query
|
107
|
+
when "no results"; :no_results
|
108
|
+
else :madison_square_garden
|
109
|
+
end
|
91
110
|
read_fixture "geocoder_ca_#{file}.json"
|
92
111
|
end
|
93
112
|
end
|
@@ -100,6 +119,23 @@ module Geocoder
|
|
100
119
|
read_fixture "freegeoip_74_200_247_59.json"
|
101
120
|
end
|
102
121
|
end
|
122
|
+
|
123
|
+
class Bing < Base
|
124
|
+
private #-----------------------------------------------------------------
|
125
|
+
def fetch_raw_data(query, reverse = false)
|
126
|
+
raise TimeoutError if query == "timeout"
|
127
|
+
if reverse
|
128
|
+
read_fixture "bing_reverse.json"
|
129
|
+
else
|
130
|
+
file = case query
|
131
|
+
when "no results"; :no_results
|
132
|
+
else :madison_square_garden
|
133
|
+
end
|
134
|
+
read_fixture "bing_#{file}.json"
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
103
139
|
end
|
104
140
|
end
|
105
141
|
|
@@ -194,7 +230,7 @@ class Test::Unit::TestCase
|
|
194
230
|
end
|
195
231
|
|
196
232
|
def all_lookups
|
197
|
-
Geocoder.
|
233
|
+
Geocoder.valid_lookups
|
198
234
|
end
|
199
235
|
|
200
236
|
def street_lookups
|