geocoder 1.0.5 → 1.1.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 +13 -0
- data/README.rdoc +14 -3
- data/Rakefile +8 -2
- data/lib/geocoder.rb +2 -6
- data/lib/geocoder/cli.rb +7 -2
- data/lib/geocoder/exceptions.rb +11 -0
- data/lib/geocoder/lookups/base.rb +12 -5
- data/lib/geocoder/lookups/geocoder_ca.rb +2 -1
- data/lib/geocoder/lookups/google.rb +2 -1
- data/lib/geocoder/lookups/nominatim.rb +37 -0
- data/lib/geocoder/results/nominatim.rb +67 -0
- data/lib/geocoder/results/yandex.rb +10 -2
- data/lib/geocoder/stores/active_record.rb +49 -24
- data/lib/geocoder/stores/base.rb +9 -10
- data/lib/geocoder/stores/mongo_base.rb +5 -4
- data/lib/geocoder/version.rb +1 -1
- data/test/error_handling_test.rb +4 -2
- data/test/fixtures/nominatim_madison_square_garden.json +150 -0
- data/test/fixtures/nominatim_no_results.json +1 -0
- data/test/geocoder_test.rb +6 -0
- data/test/integration/smoke_test.rb +24 -0
- data/test/services_test.rb +15 -0
- data/test/test_helper.rb +15 -0
- metadata +8 -2
data/CHANGELOG.rdoc
CHANGED
@@ -2,9 +2,22 @@
|
|
2
2
|
|
3
3
|
Per-release changes to Geocoder.
|
4
4
|
|
5
|
+
== 1.1.0 (2011 Dec 3)
|
6
|
+
|
7
|
+
* A block passed to geocoded_by is now always executed, even if the geocoding service returns no results. This means you need to make sure you have results before trying to assign data to your object.
|
8
|
+
* Fix issues with joins and row counts (issues #49, 86, and 108) by not using GROUP BY clause with ActiveRecord scopes.
|
9
|
+
* Fix incorrect object ID when join used (fixes issue #140).
|
10
|
+
* Fix calculation of bounding box which spans 180th meridian (thanks github.com/hwuethrich).
|
11
|
+
* Add within_bounding_box scope for ActiveRecord-based models (thanks github.com/gavinhughes and dbloete).
|
12
|
+
* Add option to raise Geocoder::OverQueryLimitError for Google geocoding service.
|
13
|
+
* Add support for Nominatim geocoding service (thanks github.com/wranglerdriver).
|
14
|
+
* Add support for API key to Geocoder.ca geocoding service (thanks github.com/ryanLonac).
|
15
|
+
* Add support for state to Yandex results (thanks github.com/tipugin).
|
16
|
+
|
5
17
|
== 1.0.5 (2011 Oct 26)
|
6
18
|
|
7
19
|
* Fix error with `rake assets:precompile` (thanks github.com/Sush).
|
20
|
+
* Fix HTTPS support (thanks github.com/rsanheim).
|
8
21
|
* Improve cache interface.
|
9
22
|
|
10
23
|
== 1.0.4 (2011 Sep 18)
|
data/README.rdoc
CHANGED
@@ -50,7 +50,7 @@ Next, your model must tell Geocoder which method returns your object's geocodabl
|
|
50
50
|
|
51
51
|
For reverse geocoding, tell Geocoder which attributes store latitude and longitude:
|
52
52
|
|
53
|
-
reverse_geocoded_by :
|
53
|
+
reverse_geocoded_by :latitude, :longitude
|
54
54
|
after_validation :reverse_geocode # auto-fetch address
|
55
55
|
|
56
56
|
=== Mongoid
|
@@ -190,7 +190,7 @@ If your model has +street+, +city+, +state+, and +country+ attributes you might
|
|
190
190
|
|
191
191
|
For reverse geocoding you can also specify an alternate name attribute where the address will be stored, for example:
|
192
192
|
|
193
|
-
reverse_geocoded_by :
|
193
|
+
reverse_geocoded_by :latitude, :longitude, :address => :location # ActiveRecord
|
194
194
|
reverse_geocoded_by :coordinates, :address => :loc # MongoDB
|
195
195
|
|
196
196
|
|
@@ -198,7 +198,7 @@ For reverse geocoding you can also specify an alternate name attribute where the
|
|
198
198
|
|
199
199
|
So far we have looked at shortcuts for assigning geocoding results to object attributes. However, if you need to do something fancy you can skip the auto-assignment by providing a block (takes the object to be geocoded and an array of <tt>Geocoder::Result</tt> objects) in which you handle the parsed geocoding result any way you like, for example:
|
200
200
|
|
201
|
-
reverse_geocoded_by :
|
201
|
+
reverse_geocoded_by :latitude, :longitude do |obj,results|
|
202
202
|
if geo = results.first
|
203
203
|
obj.city = geo.city
|
204
204
|
obj.zipcode = geo.postal_code
|
@@ -294,6 +294,17 @@ Documentation:: http://msdn.microsoft.com/en-us/library/ff701715.aspx
|
|
294
294
|
Terms of Service:: http://www.microsoft.com/maps/product/terms.html
|
295
295
|
Limitations:: No country codes or state names. Must be used on "public-facing, non-password protected web sites," "in conjunction with Bing Maps or an application that integrates Bing Maps."
|
296
296
|
|
297
|
+
==== Nominatim (<tt>:nominatim</tt>)
|
298
|
+
|
299
|
+
API key:: none
|
300
|
+
Quota:: 1 request/second
|
301
|
+
Region:: world
|
302
|
+
SSL support:: no
|
303
|
+
Languages:: ?
|
304
|
+
Documentation:: http://wiki.openstreetmap.org/wiki/Nominatim
|
305
|
+
Terms of Service:: http://wiki.openstreetmap.org/wiki/Nominatim_usage_policy
|
306
|
+
Limitations:: Please limit request rate to 1 per second and include your contact information in User-Agent headers. Data licensed under CC-BY-SA (you must provide attribution).
|
307
|
+
|
297
308
|
==== Yandex (<tt>:yandex</tt>)
|
298
309
|
|
299
310
|
API key:: required
|
data/Rakefile
CHANGED
@@ -4,11 +4,17 @@ Bundler::GemHelper.install_tasks
|
|
4
4
|
require 'rake/testtask'
|
5
5
|
Rake::TestTask.new(:test) do |test|
|
6
6
|
test.libs << 'lib' << 'test'
|
7
|
-
test.pattern = 'test
|
7
|
+
test.pattern = 'test/*_test.rb'
|
8
8
|
test.verbose = true
|
9
9
|
end
|
10
10
|
|
11
|
-
|
11
|
+
Rake::TestTask.new(:integration) do |test|
|
12
|
+
test.libs << 'lib' << 'test'
|
13
|
+
test.pattern = 'test/integration/*_test.rb'
|
14
|
+
test.verbose = true
|
15
|
+
end
|
16
|
+
|
17
|
+
task :default => [:test, :integration]
|
12
18
|
|
13
19
|
require 'rdoc/task'
|
14
20
|
Rake::RDocTask.new do |rdoc|
|
data/lib/geocoder.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require "geocoder/configuration"
|
2
2
|
require "geocoder/calculations"
|
3
|
+
require "geocoder/exceptions"
|
3
4
|
require "geocoder/cache"
|
4
5
|
require "geocoder/request"
|
5
6
|
require "geocoder/models/active_record"
|
@@ -56,7 +57,7 @@ module Geocoder
|
|
56
57
|
# All street address lookups, default first.
|
57
58
|
#
|
58
59
|
def street_lookups
|
59
|
-
[:google, :google_premier, :yahoo, :bing, :geocoder_ca, :yandex]
|
60
|
+
[:google, :google_premier, :yahoo, :bing, :geocoder_ca, :yandex, :nominatim]
|
60
61
|
end
|
61
62
|
|
62
63
|
##
|
@@ -67,11 +68,6 @@ module Geocoder
|
|
67
68
|
end
|
68
69
|
|
69
70
|
|
70
|
-
# exception classes
|
71
|
-
class Error < StandardError; end
|
72
|
-
class ConfigurationError < Error; end
|
73
|
-
|
74
|
-
|
75
71
|
private # -----------------------------------------------------------------
|
76
72
|
|
77
73
|
##
|
data/lib/geocoder/cli.rb
CHANGED
@@ -13,8 +13,13 @@ module Geocoder
|
|
13
13
|
opts.separator "\nOptions: "
|
14
14
|
|
15
15
|
opts.on("-k <key>", "--key <key>",
|
16
|
-
"Key for geocoding API (optional for most)") do |key|
|
17
|
-
|
16
|
+
"Key for geocoding API (optional for most). For Google Premier use 'key client channel' separated by spaces") do |key|
|
17
|
+
premier_key = key.split(' ')
|
18
|
+
if premier_key.length == 3
|
19
|
+
Geocoder::Configuration.api_key = premier_key
|
20
|
+
else
|
21
|
+
Geocoder::Configuration.api_key = key
|
22
|
+
end
|
18
23
|
end
|
19
24
|
|
20
25
|
opts.on("-l <language>", "--language <language>",
|
@@ -91,13 +91,17 @@ module Geocoder
|
|
91
91
|
end
|
92
92
|
|
93
93
|
##
|
94
|
-
# Raise exception
|
94
|
+
# Raise exception if configuration specifies it should be raised.
|
95
|
+
# Return false if exception not raised.
|
95
96
|
#
|
96
|
-
def raise_error(
|
97
|
-
|
97
|
+
def raise_error(error, message = nil)
|
98
|
+
if Geocoder::Configuration.always_raise.include?(error.class)
|
99
|
+
raise error, message
|
100
|
+
else
|
101
|
+
false
|
102
|
+
end
|
98
103
|
end
|
99
104
|
|
100
|
-
|
101
105
|
##
|
102
106
|
# Returns a parsed search result (Ruby hash).
|
103
107
|
#
|
@@ -141,8 +145,11 @@ module Geocoder
|
|
141
145
|
def fetch_raw_data(query, reverse = false)
|
142
146
|
timeout(Geocoder::Configuration.timeout) do
|
143
147
|
url = query_url(query, reverse)
|
148
|
+
uri = URI.parse(url)
|
144
149
|
unless cache and response = cache[url]
|
145
|
-
|
150
|
+
client = http_client.new(uri.host, uri.port)
|
151
|
+
client.use_ssl = true if Geocoder::Configuration.use_https
|
152
|
+
response = client.get(uri.request_uri).body
|
146
153
|
if cache
|
147
154
|
cache[url] = response
|
148
155
|
end
|
@@ -15,7 +15,8 @@ module Geocoder::Lookup
|
|
15
15
|
case doc['status']; when "OK" # OK status implies >0 results
|
16
16
|
return doc['results']
|
17
17
|
when "OVER_QUERY_LIMIT"
|
18
|
-
|
18
|
+
raise_error(Geocoder::OverQueryLimitError) ||
|
19
|
+
warn("Google Geocoding API error: over query limit.")
|
19
20
|
when "REQUEST_DENIED"
|
20
21
|
warn "Google Geocoding API error: request denied."
|
21
22
|
when "INVALID_REQUEST"
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'geocoder/lookups/base'
|
2
|
+
require "geocoder/results/nominatim"
|
3
|
+
|
4
|
+
module Geocoder::Lookup
|
5
|
+
class Nominatim < Base
|
6
|
+
|
7
|
+
def map_link_url(coordinates)
|
8
|
+
"http://www.openstreetmap.org/?lat=#{coordinates[0]}&lon=#{coordinates[1]}&zoom=15&layers=M"
|
9
|
+
end
|
10
|
+
|
11
|
+
private # ---------------------------------------------------------------
|
12
|
+
|
13
|
+
def results(query, reverse = false)
|
14
|
+
return [] unless doc = fetch_data(query, reverse)
|
15
|
+
doc.is_a?(Array) ? doc : [doc]
|
16
|
+
end
|
17
|
+
|
18
|
+
def query_url(query, reverse = false)
|
19
|
+
params = {
|
20
|
+
:format => "json",
|
21
|
+
:polygon => "1",
|
22
|
+
:addressdetails => "1",
|
23
|
+
:"accept-language" => Geocoder::Configuration.language
|
24
|
+
}
|
25
|
+
if (reverse)
|
26
|
+
method = 'reverse'
|
27
|
+
parts = query.split(/\s*,\s*/);
|
28
|
+
params[:lat] = parts[0]
|
29
|
+
params[:lon] = parts[1]
|
30
|
+
else
|
31
|
+
method = 'search'
|
32
|
+
params[:q] = query
|
33
|
+
end
|
34
|
+
"http://nominatim.openstreetmap.org/#{method}?" + hash_to_query(params)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'geocoder/results/base'
|
2
|
+
|
3
|
+
module Geocoder::Result
|
4
|
+
class Nominatim < Base
|
5
|
+
|
6
|
+
def house_number
|
7
|
+
@data['address']['house_number']
|
8
|
+
end
|
9
|
+
|
10
|
+
def address
|
11
|
+
@data['display_name']
|
12
|
+
end
|
13
|
+
|
14
|
+
def street
|
15
|
+
@data['address']['road']
|
16
|
+
end
|
17
|
+
|
18
|
+
def city
|
19
|
+
@data['address']['city']
|
20
|
+
end
|
21
|
+
|
22
|
+
def village
|
23
|
+
@data['address']['villiage']
|
24
|
+
end
|
25
|
+
|
26
|
+
def town
|
27
|
+
@data['address']['town']
|
28
|
+
end
|
29
|
+
|
30
|
+
def state
|
31
|
+
@data['address']['state']
|
32
|
+
end
|
33
|
+
|
34
|
+
alias_method :state_code, :state
|
35
|
+
|
36
|
+
def postal_code
|
37
|
+
@data['address']['postcode']
|
38
|
+
end
|
39
|
+
|
40
|
+
def county
|
41
|
+
@data['address']['county']
|
42
|
+
end
|
43
|
+
|
44
|
+
def country
|
45
|
+
@data['address']['country']
|
46
|
+
end
|
47
|
+
|
48
|
+
def country_code
|
49
|
+
@data['address']['country_code']
|
50
|
+
end
|
51
|
+
|
52
|
+
def coordinates
|
53
|
+
[@data['lat'].to_f, @data['lon'].to_f]
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.response_attributes
|
57
|
+
%w[place_id, osm_type, osm_id, boundingbox, license,
|
58
|
+
polygonpoints, display_name, class, type, stadium, suburb]
|
59
|
+
end
|
60
|
+
|
61
|
+
response_attributes.each do |a|
|
62
|
+
define_method a do
|
63
|
+
@data[a]
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -12,7 +12,11 @@ module Geocoder::Result
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def city
|
15
|
-
|
15
|
+
if state.empty?
|
16
|
+
address_details['Locality']['LocalityName']
|
17
|
+
else
|
18
|
+
address_details['AdministrativeArea']['Locality']['LocalityName']
|
19
|
+
end
|
16
20
|
end
|
17
21
|
|
18
22
|
def country
|
@@ -24,7 +28,11 @@ module Geocoder::Result
|
|
24
28
|
end
|
25
29
|
|
26
30
|
def state
|
27
|
-
|
31
|
+
if address_details['AdministrativeArea']
|
32
|
+
address_details['AdministrativeArea']['AdministrativeAreaName']
|
33
|
+
else
|
34
|
+
""
|
35
|
+
end
|
28
36
|
end
|
29
37
|
|
30
38
|
def state_code
|
@@ -39,6 +39,25 @@ module Geocoder::Store
|
|
39
39
|
where(:id => false) # no results if no lat/lon given
|
40
40
|
end
|
41
41
|
}
|
42
|
+
|
43
|
+
|
44
|
+
##
|
45
|
+
# Find all objects within the area of a given bounding box.
|
46
|
+
# Bounds must be an array of locations specifying the southwest
|
47
|
+
# corner followed by the northeast corner of the box
|
48
|
+
# (<tt>[[sw_lat, sw_lon], [ne_lat, ne_lon]]</tt>).
|
49
|
+
#
|
50
|
+
scope :within_bounding_box, lambda{ |bounds|
|
51
|
+
sw_lat, sw_lng, ne_lat, ne_lng = bounds.flatten if bounds
|
52
|
+
return where(:id => false) unless sw_lat && sw_lng && ne_lat && ne_lng
|
53
|
+
spans = "latitude BETWEEN #{sw_lat} AND #{ne_lat} AND "
|
54
|
+
spans << if sw_lng > ne_lng # Handle a box that spans 180
|
55
|
+
"longitude BETWEEN #{sw_lng} AND 180 OR longitude BETWEEN -180 AND #{ne_lng}"
|
56
|
+
else
|
57
|
+
"longitude BETWEEN #{sw_lng} AND #{ne_lng}"
|
58
|
+
end
|
59
|
+
{ :conditions => spans }
|
60
|
+
}
|
42
61
|
end
|
43
62
|
end
|
44
63
|
|
@@ -114,12 +133,12 @@ module Geocoder::Store
|
|
114
133
|
"POWER(SIN((#{latitude} - #{lat_attr}) * PI() / 180 / 2), 2) + " +
|
115
134
|
"COS(#{latitude} * PI() / 180) * COS(#{lat_attr} * PI() / 180) * " +
|
116
135
|
"POWER(SIN((#{longitude} - #{lon_attr}) * PI() / 180 / 2), 2) ))"
|
117
|
-
|
136
|
+
conditions = ["#{distance} <= ?", radius]
|
118
137
|
default_near_scope_options(latitude, longitude, radius, options).merge(
|
119
|
-
:select => "#{options[:select] ||
|
138
|
+
:select => "#{options[:select] || "#{table_name}.*"}, " +
|
120
139
|
"#{distance} AS distance" +
|
121
140
|
(bearing ? ", #{bearing} AS bearing" : ""),
|
122
|
-
:
|
141
|
+
:conditions => add_exclude_condition(conditions, options[:exclude])
|
123
142
|
)
|
124
143
|
end
|
125
144
|
|
@@ -155,11 +174,16 @@ module Geocoder::Store
|
|
155
174
|
|
156
175
|
distance = "(#{dy} * ABS(#{lat_attr} - #{latitude}) * #{factor}) + " +
|
157
176
|
"(#{dx} * ABS(#{lon_attr} - #{longitude}) * #{factor})"
|
177
|
+
b = Geocoder::Calculations.bounding_box([latitude, longitude], radius, options)
|
178
|
+
conditions = [
|
179
|
+
"#{lat_attr} BETWEEN ? AND ? AND #{lon_attr} BETWEEN ? AND ?"] +
|
180
|
+
[b[0], b[2], b[1], b[3]
|
181
|
+
]
|
158
182
|
default_near_scope_options(latitude, longitude, radius, options).merge(
|
159
|
-
:select => "#{options[:select] ||
|
183
|
+
:select => "#{options[:select] || "#{table_name}.*"}, " +
|
160
184
|
"#{distance} AS distance" +
|
161
185
|
(bearing ? ", #{bearing} AS bearing" : ""),
|
162
|
-
:
|
186
|
+
:conditions => add_exclude_condition(conditions, options[:exclude])
|
163
187
|
)
|
164
188
|
end
|
165
189
|
|
@@ -167,24 +191,24 @@ module Geocoder::Store
|
|
167
191
|
# Options used for any near-like scope.
|
168
192
|
#
|
169
193
|
def default_near_scope_options(latitude, longitude, radius, options)
|
170
|
-
lat_attr = geocoder_options[:latitude]
|
171
|
-
lon_attr = geocoder_options[:longitude]
|
172
|
-
b = Geocoder::Calculations.bounding_box([latitude, longitude], radius, options)
|
173
|
-
conditions = \
|
174
|
-
["#{lat_attr} BETWEEN ? AND ? AND #{lon_attr} BETWEEN ? AND ?"] +
|
175
|
-
[b[0], b[2], b[1], b[3]]
|
176
|
-
if obj = options[:exclude]
|
177
|
-
conditions[0] << " AND #{table_name}.id != ?"
|
178
|
-
conditions << obj.id
|
179
|
-
end
|
180
194
|
{
|
181
|
-
:
|
182
|
-
:order => options[:order],
|
195
|
+
:order => options[:order] || "distance",
|
183
196
|
:limit => options[:limit],
|
184
|
-
:offset => options[:offset]
|
185
|
-
:conditions => conditions
|
197
|
+
:offset => options[:offset]
|
186
198
|
}
|
187
199
|
end
|
200
|
+
|
201
|
+
##
|
202
|
+
# Adds a condition to exclude a given object by ID.
|
203
|
+
# The given conditions MUST be an array.
|
204
|
+
#
|
205
|
+
def add_exclude_condition(conditions, exclude)
|
206
|
+
if exclude
|
207
|
+
conditions[0] << " AND #{table_name}.id != ?"
|
208
|
+
conditions << exclude.id
|
209
|
+
end
|
210
|
+
conditions
|
211
|
+
end
|
188
212
|
end
|
189
213
|
|
190
214
|
##
|
@@ -193,12 +217,13 @@ module Geocoder::Store
|
|
193
217
|
#
|
194
218
|
def geocode
|
195
219
|
do_lookup(false) do |o,rs|
|
196
|
-
r = rs.first
|
197
|
-
|
198
|
-
|
199
|
-
|
220
|
+
if r = rs.first
|
221
|
+
unless r.latitude.nil? or r.longitude.nil?
|
222
|
+
o.send :write_attribute, self.class.geocoder_options[:latitude], r.latitude
|
223
|
+
o.send :write_attribute, self.class.geocoder_options[:longitude], r.longitude
|
224
|
+
end
|
225
|
+
r.coordinates
|
200
226
|
end
|
201
|
-
r.coordinates
|
202
227
|
end
|
203
228
|
end
|
204
229
|
|
data/lib/geocoder/stores/base.rb
CHANGED
@@ -98,18 +98,17 @@ module Geocoder
|
|
98
98
|
return
|
99
99
|
end
|
100
100
|
|
101
|
-
|
101
|
+
results = Geocoder.search(query)
|
102
102
|
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
103
|
+
# execute custom block, if specified in configuration
|
104
|
+
block_key = reverse ? :reverse_block : :geocode_block
|
105
|
+
if custom_block = options[block_key]
|
106
|
+
custom_block.call(self, results)
|
107
107
|
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
end
|
108
|
+
# else execute block passed directly to this method,
|
109
|
+
# which generally performs the "auto-assigns"
|
110
|
+
elsif block_given?
|
111
|
+
yield(self, results)
|
113
112
|
end
|
114
113
|
end
|
115
114
|
end
|
@@ -56,11 +56,12 @@ module Geocoder::Store
|
|
56
56
|
#
|
57
57
|
def geocode
|
58
58
|
do_lookup(false) do |o,rs|
|
59
|
-
r = rs.first
|
60
|
-
|
61
|
-
|
59
|
+
if r = rs.first
|
60
|
+
unless r.coordinates.nil?
|
61
|
+
o.send :write_attribute, self.class.geocoder_options[:coordinates], r.coordinates.reverse
|
62
|
+
end
|
63
|
+
r.coordinates
|
62
64
|
end
|
63
|
-
r.coordinates
|
64
65
|
end
|
65
66
|
end
|
66
67
|
|
data/lib/geocoder/version.rb
CHANGED
data/test/error_handling_test.rb
CHANGED
@@ -3,6 +3,10 @@ require 'test_helper'
|
|
3
3
|
|
4
4
|
class ErrorHandlingTest < Test::Unit::TestCase
|
5
5
|
|
6
|
+
def teardown
|
7
|
+
Geocoder::Configuration.always_raise = []
|
8
|
+
end
|
9
|
+
|
6
10
|
def test_does_not_choke_on_timeout
|
7
11
|
# keep test output clean: suppress timeout warning
|
8
12
|
orig = $VERBOSE; $VERBOSE = nil
|
@@ -21,7 +25,6 @@ class ErrorHandlingTest < Test::Unit::TestCase
|
|
21
25
|
lookup.send(:results, "timeout")
|
22
26
|
end
|
23
27
|
end
|
24
|
-
Geocoder::Configuration.always_raise = []
|
25
28
|
end
|
26
29
|
|
27
30
|
def test_always_raise_socket_error
|
@@ -32,6 +35,5 @@ class ErrorHandlingTest < Test::Unit::TestCase
|
|
32
35
|
lookup.send(:results, "socket_error")
|
33
36
|
end
|
34
37
|
end
|
35
|
-
Geocoder::Configuration.always_raise = []
|
36
38
|
end
|
37
39
|
end
|
@@ -0,0 +1,150 @@
|
|
1
|
+
[
|
2
|
+
|
3
|
+
{
|
4
|
+
"place_id": "30632629",
|
5
|
+
"licence": "Data Copyright OpenStreetMap Contributors, Some Rights Reserved. CC-BY-SA 2.0.",
|
6
|
+
"osm_type": "way",
|
7
|
+
"osm_id": "24801588",
|
8
|
+
"boundingbox": [
|
9
|
+
"40.749828338623",
|
10
|
+
"40.7511596679688",
|
11
|
+
"-73.9943389892578",
|
12
|
+
"-73.9926528930664"
|
13
|
+
],
|
14
|
+
"polygonpoints": [
|
15
|
+
[
|
16
|
+
"-73.9943346",
|
17
|
+
"40.7503638"
|
18
|
+
],
|
19
|
+
[
|
20
|
+
"-73.9942745",
|
21
|
+
"40.7504158"
|
22
|
+
],
|
23
|
+
[
|
24
|
+
"-73.9942593",
|
25
|
+
"40.750629"
|
26
|
+
],
|
27
|
+
[
|
28
|
+
"-73.9941343",
|
29
|
+
"40.7508432"
|
30
|
+
],
|
31
|
+
[
|
32
|
+
"-73.9939794",
|
33
|
+
"40.7509703"
|
34
|
+
],
|
35
|
+
[
|
36
|
+
"-73.9938042",
|
37
|
+
"40.7510532"
|
38
|
+
],
|
39
|
+
[
|
40
|
+
"-73.9938025",
|
41
|
+
"40.7511311"
|
42
|
+
],
|
43
|
+
[
|
44
|
+
"-73.9936051",
|
45
|
+
"40.7511571"
|
46
|
+
],
|
47
|
+
[
|
48
|
+
"-73.9935673",
|
49
|
+
"40.751105"
|
50
|
+
],
|
51
|
+
[
|
52
|
+
"-73.9934095",
|
53
|
+
"40.7511089"
|
54
|
+
],
|
55
|
+
[
|
56
|
+
"-73.9931235",
|
57
|
+
"40.7510548"
|
58
|
+
],
|
59
|
+
[
|
60
|
+
"-73.9928863",
|
61
|
+
"40.7509311"
|
62
|
+
],
|
63
|
+
[
|
64
|
+
"-73.9928068",
|
65
|
+
"40.750949"
|
66
|
+
],
|
67
|
+
[
|
68
|
+
"-73.992721",
|
69
|
+
"40.7508515"
|
70
|
+
],
|
71
|
+
[
|
72
|
+
"-73.9927444",
|
73
|
+
"40.7507889"
|
74
|
+
],
|
75
|
+
[
|
76
|
+
"-73.9926693",
|
77
|
+
"40.7506457"
|
78
|
+
],
|
79
|
+
[
|
80
|
+
"-73.9926597",
|
81
|
+
"40.7503657"
|
82
|
+
],
|
83
|
+
[
|
84
|
+
"-73.9928305",
|
85
|
+
"40.7500953"
|
86
|
+
],
|
87
|
+
[
|
88
|
+
"-73.9929757",
|
89
|
+
"40.7499911"
|
90
|
+
],
|
91
|
+
[
|
92
|
+
"-73.9931281",
|
93
|
+
"40.7499238"
|
94
|
+
],
|
95
|
+
[
|
96
|
+
"-73.993133",
|
97
|
+
"40.7498631"
|
98
|
+
],
|
99
|
+
[
|
100
|
+
"-73.9932961",
|
101
|
+
"40.7498306"
|
102
|
+
],
|
103
|
+
[
|
104
|
+
"-73.9933664",
|
105
|
+
"40.7498742"
|
106
|
+
],
|
107
|
+
[
|
108
|
+
"-73.993471",
|
109
|
+
"40.7498701"
|
110
|
+
],
|
111
|
+
[
|
112
|
+
"-73.9938023",
|
113
|
+
"40.7499263"
|
114
|
+
],
|
115
|
+
[
|
116
|
+
"-73.9940703",
|
117
|
+
"40.7500756"
|
118
|
+
],
|
119
|
+
[
|
120
|
+
"-73.9941876",
|
121
|
+
"40.7502038"
|
122
|
+
],
|
123
|
+
[
|
124
|
+
"-73.9942831",
|
125
|
+
"40.7502142"
|
126
|
+
],
|
127
|
+
[
|
128
|
+
"-73.9943346",
|
129
|
+
"40.7503638"
|
130
|
+
]
|
131
|
+
],
|
132
|
+
"lat": "40.7504928941818",
|
133
|
+
"lon": "-73.993466492276",
|
134
|
+
"display_name": "Madison Square Garden, West 31st Street, Long Island City, New York City, New York, 10001, United States of America",
|
135
|
+
"class": "leisure",
|
136
|
+
"type": "stadium",
|
137
|
+
"address": {
|
138
|
+
"stadium": "Madison Square Garden",
|
139
|
+
"road": "West 31st Street",
|
140
|
+
"suburb": "Long Island City",
|
141
|
+
"city": "New York City",
|
142
|
+
"county": "New York",
|
143
|
+
"state": "New York",
|
144
|
+
"postcode": "10001",
|
145
|
+
"country": "United States of America",
|
146
|
+
"country_code": "us"
|
147
|
+
}
|
148
|
+
}
|
149
|
+
|
150
|
+
]
|
@@ -0,0 +1 @@
|
|
1
|
+
[ ]
|
data/test/geocoder_test.rb
CHANGED
@@ -32,6 +32,12 @@ class GeocoderTest < Test::Unit::TestCase
|
|
32
32
|
assert_equal coords, [v.latitude, v.longitude]
|
33
33
|
end
|
34
34
|
|
35
|
+
def test_geocode_block_executed_when_no_results
|
36
|
+
v = Event.new("Nowhere", "no results")
|
37
|
+
v.geocode
|
38
|
+
assert_equal "NOT FOUND", v.coords_string
|
39
|
+
end
|
40
|
+
|
35
41
|
def test_reverse_geocode_assigns_and_returns_address
|
36
42
|
v = Landmark.new(*landmark_params(:msg))
|
37
43
|
address = "4 Penn Plaza, New York, NY 10001, USA"
|
@@ -0,0 +1,24 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), *%w[ .. .. lib]))
|
2
|
+
require 'pathname'
|
3
|
+
require 'rubygems'
|
4
|
+
require 'test/unit'
|
5
|
+
require 'geocoder'
|
6
|
+
|
7
|
+
class SmokeTest < Test::Unit::TestCase
|
8
|
+
|
9
|
+
def test_simple_zip_code_search
|
10
|
+
result = Geocoder.search "27701"
|
11
|
+
assert_equal "Durham", result.first.city
|
12
|
+
assert_equal "North Carolina", result.first.state
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_simple_zip_code_search_with_ssl
|
16
|
+
Geocoder::Configuration.use_https = true
|
17
|
+
result = Geocoder.search "27701"
|
18
|
+
assert_equal "Durham", result.first.city
|
19
|
+
assert_equal "North Carolina", result.first.state
|
20
|
+
ensure
|
21
|
+
Geocoder::Configuration.use_https = false
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
data/test/services_test.rb
CHANGED
@@ -110,4 +110,19 @@ class ServicesTest < Test::Unit::TestCase
|
|
110
110
|
results = Geocoder.search("no results")
|
111
111
|
assert_equal 0, results.length
|
112
112
|
end
|
113
|
+
|
114
|
+
# --- Nominatim ---
|
115
|
+
|
116
|
+
def test_nominatim_result_components
|
117
|
+
Geocoder::Configuration.lookup = :nominatim
|
118
|
+
result = Geocoder.search("Madison Square Garden, New York, NY").first
|
119
|
+
assert_equal "10001", result.postal_code
|
120
|
+
end
|
121
|
+
|
122
|
+
def test_nominatim_address_formatting
|
123
|
+
Geocoder::Configuration.lookup = :nominatim
|
124
|
+
result = Geocoder.search("Madison Square Garden, New York, NY").first
|
125
|
+
assert_equal "Madison Square Garden, West 31st Street, Long Island City, New York City, New York, 10001, United States of America",
|
126
|
+
result.address
|
127
|
+
end
|
113
128
|
end
|
data/test/test_helper.rb
CHANGED
@@ -150,6 +150,19 @@ module Geocoder
|
|
150
150
|
end
|
151
151
|
end
|
152
152
|
|
153
|
+
class Nominatim < Base
|
154
|
+
private #-----------------------------------------------------------------
|
155
|
+
def fetch_raw_data(query, reverse = false)
|
156
|
+
raise TimeoutError if query == "timeout"
|
157
|
+
raise SocketError if query == "socket_error"
|
158
|
+
file = case query
|
159
|
+
when "no results"; :no_results
|
160
|
+
else :madison_square_garden
|
161
|
+
end
|
162
|
+
read_fixture "nominatim_#{file}.json"
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
153
166
|
end
|
154
167
|
end
|
155
168
|
|
@@ -187,6 +200,8 @@ class Event < ActiveRecord::Base
|
|
187
200
|
geocoded_by :address do |obj,results|
|
188
201
|
if result = results.first
|
189
202
|
obj.coords_string = "#{result.latitude},#{result.longitude}"
|
203
|
+
else
|
204
|
+
obj.coords_string = "NOT FOUND"
|
190
205
|
end
|
191
206
|
end
|
192
207
|
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: geocoder
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 1.0
|
5
|
+
version: 1.1.0
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Alex Reisner
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2011-
|
13
|
+
date: 2011-12-03 00:00:00 -05:00
|
14
14
|
default_executable:
|
15
15
|
dependencies: []
|
16
16
|
|
@@ -35,12 +35,14 @@ files:
|
|
35
35
|
- lib/geocoder/calculations.rb
|
36
36
|
- lib/geocoder/cli.rb
|
37
37
|
- lib/geocoder/configuration.rb
|
38
|
+
- lib/geocoder/exceptions.rb
|
38
39
|
- lib/geocoder/lookups/base.rb
|
39
40
|
- lib/geocoder/lookups/bing.rb
|
40
41
|
- lib/geocoder/lookups/freegeoip.rb
|
41
42
|
- lib/geocoder/lookups/geocoder_ca.rb
|
42
43
|
- lib/geocoder/lookups/google.rb
|
43
44
|
- lib/geocoder/lookups/google_premier.rb
|
45
|
+
- lib/geocoder/lookups/nominatim.rb
|
44
46
|
- lib/geocoder/lookups/yahoo.rb
|
45
47
|
- lib/geocoder/lookups/yandex.rb
|
46
48
|
- lib/geocoder/models/active_record.rb
|
@@ -56,6 +58,7 @@ files:
|
|
56
58
|
- lib/geocoder/results/geocoder_ca.rb
|
57
59
|
- lib/geocoder/results/google.rb
|
58
60
|
- lib/geocoder/results/google_premier.rb
|
61
|
+
- lib/geocoder/results/nominatim.rb
|
59
62
|
- lib/geocoder/results/yahoo.rb
|
60
63
|
- lib/geocoder/results/yandex.rb
|
61
64
|
- lib/geocoder/stores/active_record.rb
|
@@ -82,6 +85,8 @@ files:
|
|
82
85
|
- test/fixtures/google_no_city_data.json
|
83
86
|
- test/fixtures/google_no_locality.json
|
84
87
|
- test/fixtures/google_no_results.json
|
88
|
+
- test/fixtures/nominatim_madison_square_garden.json
|
89
|
+
- test/fixtures/nominatim_no_results.json
|
85
90
|
- test/fixtures/yahoo_garbage.json
|
86
91
|
- test/fixtures/yahoo_madison_square_garden.json
|
87
92
|
- test/fixtures/yahoo_no_results.json
|
@@ -91,6 +96,7 @@ files:
|
|
91
96
|
- test/geocoder_test.rb
|
92
97
|
- test/https_test.rb
|
93
98
|
- test/input_handling_test.rb
|
99
|
+
- test/integration/smoke_test.rb
|
94
100
|
- test/lookup_test.rb
|
95
101
|
- test/method_aliases_test.rb
|
96
102
|
- test/mongoid_test.rb
|