geokit 1.8.3 → 1.8.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,8 @@
1
+ ## 1.8.4
2
+
3
+ * Fix math error in ruby 1.8
4
+ * Extract HTTP processing to allow different HTTP clients for caching, etc.
5
+
1
6
  ## 1.8.3
2
7
 
3
8
  * Fix MultiGeocoder with geocoders that only have one argument
@@ -31,4 +31,5 @@ Gem::Specification.new do |spec|
31
31
  spec.add_development_dependency 'coveralls'
32
32
  spec.add_development_dependency 'vcr'
33
33
  spec.add_development_dependency 'webmock' # used in vcr
34
+ spec.add_development_dependency 'typhoeus' # used in net_adapter
34
35
  end
@@ -1,4 +1,6 @@
1
1
  require 'net/http'
2
+ require 'geokit/net_adapter/net_http'
3
+ require 'geokit/net_adapter/typhoeus'
2
4
  require 'ipaddr'
3
5
  require 'rexml/document'
4
6
  require 'yaml'
@@ -37,6 +39,7 @@ module Geokit
37
39
  @@logger=Logger.new(STDOUT)
38
40
  @@logger.level=Logger::INFO
39
41
  @@domain = nil
42
+ @@net_adapter = Geokit::NetAdapter::NetHttp
40
43
 
41
44
  def self.__define_accessors
42
45
  class_variables.each do |v|
@@ -141,15 +144,11 @@ module Geokit
141
144
 
142
145
  # Wraps the geocoder call around a proxy if necessary.
143
146
  def self.do_get(url)
144
- uri = URI.parse(url)
145
- req = Net::HTTP::Get.new(url)
146
- req.basic_auth(uri.user, uri.password) if uri.userinfo
147
- net_http_args = [uri.host, uri.port]
148
- if (proxy_uri_string = Geokit::Geocoders::proxy)
149
- proxy_uri = URI.parse(proxy_uri_string)
150
- net_http_args += [proxy_uri.host, proxy_uri.port, proxy_uri.user, proxy_uri.password]
151
- end
152
- Net::HTTP::new(*net_http_args).start { |http| http.request(req) }
147
+ net_adapter.do_get(url)
148
+ end
149
+
150
+ def self.net_adapter
151
+ Geokit::Geocoders::net_adapter
153
152
  end
154
153
 
155
154
  def self.provider_name
@@ -174,7 +173,7 @@ module Geokit
174
173
 
175
174
  def self.process(format, url, *args)
176
175
  res = call_geocoder_service(url)
177
- return GeoLoc.new if !res.is_a?(Net::HTTPSuccess)
176
+ return GeoLoc.new unless net_adapter.success?(res)
178
177
  parse format, res.body, *args
179
178
  end
180
179
 
@@ -11,7 +11,7 @@ module Geokit
11
11
  def self.do_geocode(address)
12
12
  url = submit_url(address)
13
13
  res = call_geocoder_service(url)
14
- return GeoLoc.new if !res.is_a?(Net::HTTPSuccess)
14
+ return GeoLoc.new unless net_adapter.success?(res)
15
15
  xml = transcode_to_utf8(res.body)
16
16
  parse :xml, xml
17
17
  end
@@ -140,36 +140,41 @@ module Geokit
140
140
  loc.lat = ll['lat'].to_f
141
141
  loc.lng = ll['lng'].to_f
142
142
 
143
+ set_bounds(loc, addr)
144
+
145
+ loc
146
+ end
147
+
148
+ def self.set_bounds(loc, addr)
143
149
  viewport = addr['geometry']['viewport']
144
150
  ne = Geokit::LatLng.from_json(viewport['northeast'])
145
151
  sw = Geokit::LatLng.from_json(viewport['southwest'])
146
152
  loc.suggested_bounds = Geokit::Bounds.new(sw, ne)
147
-
148
- loc
149
153
  end
150
154
 
151
155
  def self.set_address_components(loc, addr)
152
156
  addr['address_components'].each do |comp|
157
+ types = comp['types']
153
158
  case
154
- when comp['types'].include?("subpremise")
159
+ when types.include?("subpremise")
155
160
  loc.sub_premise = comp['short_name']
156
- when comp['types'].include?("street_number")
161
+ when types.include?("street_number")
157
162
  loc.street_number = comp['short_name']
158
- when comp['types'].include?("route")
163
+ when types.include?("route")
159
164
  loc.street_name = comp['long_name']
160
- when comp['types'].include?("locality")
165
+ when types.include?("locality")
161
166
  loc.city = comp['long_name']
162
- when comp['types'].include?("administrative_area_level_1")
167
+ when types.include?("administrative_area_level_1")
163
168
  loc.state = comp['short_name']
164
169
  loc.province = comp['short_name']
165
- when comp['types'].include?("postal_code")
170
+ when types.include?("postal_code")
166
171
  loc.zip = comp['long_name']
167
- when comp['types'].include?("country")
172
+ when types.include?("country")
168
173
  loc.country_code = comp['short_name']
169
174
  loc.country = comp['long_name']
170
- when comp['types'].include?("administrative_area_level_2")
175
+ when types.include?("administrative_area_level_2")
171
176
  loc.district = comp['long_name']
172
- when comp['types'].include?('neighborhood')
177
+ when types.include?('neighborhood')
173
178
  loc.neighborhood = comp['short_name']
174
179
  end
175
180
  end
@@ -13,7 +13,7 @@ module Geokit
13
13
  return GeoLoc.new unless valid_ip?(ip)
14
14
  url = submit_url(ip)
15
15
  res = call_geocoder_service(url)
16
- return GeoLoc.new if !res.is_a?(Net::HTTPSuccess)
16
+ return GeoLoc.new unless net_adapter.success?(res)
17
17
  ensure_utf8_encoding(res)
18
18
  body = res.body
19
19
  body = body.encode('UTF-8') if body.respond_to? :encode
@@ -60,12 +60,10 @@ module Geokit
60
60
  Math.sqrt(lat_length ** 2 + lng_length ** 2)
61
61
  end
62
62
 
63
+ # Ruby 1.9 raises {Math::DomainError}, but it is not defined in Ruby 1.8
63
64
  def math_error_classes
64
- error_classes = [Errno::EDOM]
65
-
66
- # Ruby 1.9 raises {Math::DomainError}, but it is not defined in Ruby
67
- # 1.8. Backwards-compatibly rescue both errors.
68
- error_classes << Math::DomainError if defined?(Math::DomainError)
65
+ return [Errno::EDOM, Math::DomainError] if defined?(Math::DomainError)
66
+ [Errno::EDOM]
69
67
  end
70
68
 
71
69
  # Returns heading in degrees (0 is north, 90 is east, 180 is south, etc)
@@ -0,0 +1,21 @@
1
+ module Geokit
2
+ module NetAdapter
3
+ class NetHttp
4
+ def self.do_get(url)
5
+ uri = URI.parse(url)
6
+ req = Net::HTTP::Get.new(url)
7
+ req.basic_auth(uri.user, uri.password) if uri.userinfo
8
+ net_http_args = [uri.host, uri.port]
9
+ if (proxy_uri_string = Geokit::Geocoders::proxy)
10
+ proxy_uri = URI.parse(proxy_uri_string)
11
+ net_http_args += [proxy_uri.host, proxy_uri.port, proxy_uri.user, proxy_uri.password]
12
+ end
13
+ Net::HTTP::new(*net_http_args).start { |http| http.request(req) }
14
+ end
15
+
16
+ def self.success?(response)
17
+ response.is_a?(Net::HTTPSuccess)
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,13 @@
1
+ module Geokit
2
+ module NetAdapter
3
+ class Typhoeus
4
+ def self.do_get(url)
5
+ ::Typhoeus.get(url.to_s)
6
+ end
7
+
8
+ def self.success?(response)
9
+ response.success?
10
+ end
11
+ end
12
+ end
13
+ end
@@ -2,42 +2,36 @@ module Geokit
2
2
  # A complex polygon made of multiple points. End point must equal start point to close the poly.
3
3
  class Polygon
4
4
 
5
- attr_accessor :poly_y, :poly_x
5
+ attr_accessor :points
6
6
 
7
+ # Pass in an array of Geokit::LatLng
7
8
  def initialize(points)
8
- # Pass in an array of Geokit::LatLng
9
- @poly_x = []
10
- @poly_y = []
11
-
12
- points.each do |point|
13
- @poly_x << point.lng
14
- @poly_y << point.lat
15
- end
9
+ @points = points
16
10
 
17
11
  # A Polygon must be 'closed', the last point equal to the first point
18
- if @poly_x[0] != @poly_x[-1] || @poly_y[0] != @poly_y[-1]
19
- # Append the first point to the array to close the polygon
20
- @poly_x << @poly_x[0]
21
- @poly_y << @poly_y[0]
22
- end
23
-
12
+ # Append the first point to the array to close the polygon
13
+ @points << points[0] if points[0] != points[-1]
24
14
  end
25
15
 
26
16
  def contains?(point)
27
- j = @poly_x.length - 1
17
+ last_point = @points[-1]
28
18
  oddNodes = false
29
19
  x = point.lng
30
20
  y = point.lat
31
21
 
32
- for i in (0..j)
33
- if (@poly_y[i] < y && @poly_y[j] >= y ||
34
- @poly_y[j] < y && @poly_y[i] >= y)
35
- if (@poly_x[i] + (y - @poly_y[i]) / (@poly_y[j] - @poly_y[i]) * (@poly_x[j] - @poly_x[i]) < x)
22
+ for p in @points
23
+ yi = p.lat
24
+ xi = p.lng
25
+ yj = last_point.lat
26
+ xj = last_point.lng
27
+ if (yi < y && yj >= y ||
28
+ yj < y && yi >= y)
29
+ if (xi + (y - yi) / (yj - yi) * (xj - xi) < x)
36
30
  oddNodes = !oddNodes
37
31
  end
38
32
  end
39
33
 
40
- j=i
34
+ last_point = p
41
35
  end
42
36
 
43
37
  oddNodes
@@ -1,3 +1,3 @@
1
1
  module Geokit
2
- VERSION = '1.8.3'
2
+ VERSION = '1.8.4'
3
3
  end
@@ -11,7 +11,7 @@ end
11
11
  require 'geoip'
12
12
 
13
13
  if ENV['COVERAGE']
14
- COVERAGE_THRESHOLD = 90
14
+ COVERAGE_THRESHOLD = 91
15
15
  require 'simplecov'
16
16
  require 'simplecov-rcov'
17
17
  require 'coveralls'
@@ -42,6 +42,10 @@ class MockSuccess < Net::HTTPSuccess #:nodoc: all
42
42
  def initialize
43
43
  @header = {}
44
44
  end
45
+
46
+ def success? # Typhoeus
47
+ true
48
+ end
45
49
  end
46
50
 
47
51
  class MockFailure < Net::HTTPServiceUnavailable #:nodoc: all
@@ -0,0 +1,12 @@
1
+ require File.join(File.dirname(__FILE__), 'helper')
2
+
3
+ class MappableTest < Test::Unit::TestCase #:nodoc: all
4
+
5
+ def test_math_error_classes
6
+ error_case = 0.49 * 180
7
+ from = Geokit::LatLng.new(error_case, error_case)
8
+ to = Geokit::LatLng.new(error_case, error_case)
9
+ assert_equal 0.0, Geokit::LatLng.distance_between_sphere(from, to, :kms)
10
+ end
11
+
12
+ end
@@ -0,0 +1,46 @@
1
+ require File.join(File.dirname(__FILE__), 'helper')
2
+
3
+ # Base class for testing geocoders.
4
+ class NetAdapterTest < Test::Unit::TestCase #:nodoc: all
5
+ class Geokit::Geocoders::CachedGeocoder < Geokit::Geocoders::Geocoder
6
+ def self.parse_json(hash)
7
+ hash
8
+ end
9
+ end
10
+
11
+ class SuperSimpleCache
12
+ def initialize
13
+ @cache = {}
14
+ end
15
+
16
+ def write(key, value)
17
+ @cache[key] = value
18
+ end
19
+
20
+ def fetch(key)
21
+ @cache[key]
22
+ end
23
+ end
24
+
25
+ RESULT = '{"name":"json"}'
26
+ RESULT_HASH = {"name" => "json"}
27
+
28
+ # Defines common test fixtures.
29
+ def setup
30
+ @url = 'http://www.cacheme.com'
31
+ @address = 'San Francisco, CA'
32
+ end
33
+
34
+ def test_cache
35
+ old_adapter = Geokit::Geocoders::net_adapter
36
+ Geokit::Geocoders::net_adapter = Geokit::NetAdapter::Typhoeus
37
+ Typhoeus::Config.cache = SuperSimpleCache
38
+ success = MockSuccess.new
39
+ success.expects(:body).returns(RESULT)
40
+ url = 'http://www.cacheme.com'
41
+ Geokit::NetAdapter::Typhoeus.expects(:do_get).with(@url).returns(success)
42
+ assert_equal RESULT_HASH, Geokit::Geocoders::CachedGeocoder.process(:json, @url)
43
+ Typhoeus::Config.cache = nil
44
+ Geokit::Geocoders::net_adapter = old_adapter
45
+ end
46
+ end
@@ -93,8 +93,8 @@ class PolygonTest < Test::Unit::TestCase #:nodoc: all
93
93
  #puts "\t Does poly_x[0] (#{@open_polygon.poly_x[0]}) == poly_x[-1] (#{@open_polygon.poly_x[-1]}) ?"
94
94
  #puts "\t Does poly_y[0] (#{@open_polygon.poly_y[0]}) == poly_y[-1] (#{@open_polygon.poly_y[-1]}) ?"
95
95
 
96
- assert @open_polygon.poly_x[0] == @open_polygon.poly_x[-1]
97
- assert @open_polygon.poly_y[0] == @open_polygon.poly_y[-1]
96
+ assert @open_polygon.points[0].lng == @open_polygon.points[-1].lng
97
+ assert @open_polygon.points[0].lat == @open_polygon.points[-1].lat
98
98
 
99
99
  end
100
100
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: geokit
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.8.3
4
+ version: 1.8.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -12,7 +12,7 @@ authors:
12
12
  autorequire:
13
13
  bindir: bin
14
14
  cert_chain: []
15
- date: 2013-12-31 00:00:00.000000000 Z
15
+ date: 2014-01-12 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: multi_json
@@ -158,6 +158,22 @@ dependencies:
158
158
  - - ! '>='
159
159
  - !ruby/object:Gem::Version
160
160
  version: '0'
161
+ - !ruby/object:Gem::Dependency
162
+ name: typhoeus
163
+ requirement: !ruby/object:Gem::Requirement
164
+ none: false
165
+ requirements:
166
+ - - ! '>='
167
+ - !ruby/object:Gem::Version
168
+ version: '0'
169
+ type: :development
170
+ prerelease: false
171
+ version_requirements: !ruby/object:Gem::Requirement
172
+ none: false
173
+ requirements:
174
+ - - ! '>='
175
+ - !ruby/object:Gem::Version
176
+ version: '0'
161
177
  description: Geokit provides geocoding and distance calculation in an easy-to-use
162
178
  API
163
179
  email:
@@ -220,6 +236,8 @@ files:
220
236
  - lib/geokit/lat_lng.rb
221
237
  - lib/geokit/mappable.rb
222
238
  - lib/geokit/multi_geocoder.rb
239
+ - lib/geokit/net_adapter/net_http.rb
240
+ - lib/geokit/net_adapter/typhoeus.rb
223
241
  - lib/geokit/polygon.rb
224
242
  - lib/geokit/version.rb
225
243
  - test/helper.rb
@@ -236,9 +254,11 @@ files:
236
254
  - test/test_inflector.rb
237
255
  - test/test_ipgeocoder.rb
238
256
  - test/test_latlng.rb
257
+ - test/test_mappable.rb
239
258
  - test/test_maxmind_geocoder.rb
240
259
  - test/test_multi_geocoder.rb
241
260
  - test/test_multi_ip_geocoder.rb
261
+ - test/test_net_adapter.rb
242
262
  - test/test_openstreetmap_geocoder.rb
243
263
  - test/test_polygon_contains.rb
244
264
  - test/test_ripe_geocoder.rb
@@ -262,7 +282,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
262
282
  version: '0'
263
283
  segments:
264
284
  - 0
265
- hash: -1638925415436466829
285
+ hash: -1117828600571501675
266
286
  required_rubygems_version: !ruby/object:Gem::Requirement
267
287
  none: false
268
288
  requirements:
@@ -271,7 +291,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
271
291
  version: '0'
272
292
  segments:
273
293
  - 0
274
- hash: -1638925415436466829
294
+ hash: -1117828600571501675
275
295
  requirements: []
276
296
  rubyforge_project:
277
297
  rubygems_version: 1.8.25
@@ -293,9 +313,11 @@ test_files:
293
313
  - test/test_inflector.rb
294
314
  - test/test_ipgeocoder.rb
295
315
  - test/test_latlng.rb
316
+ - test/test_mappable.rb
296
317
  - test/test_maxmind_geocoder.rb
297
318
  - test/test_multi_geocoder.rb
298
319
  - test/test_multi_ip_geocoder.rb
320
+ - test/test_net_adapter.rb
299
321
  - test/test_openstreetmap_geocoder.rb
300
322
  - test/test_polygon_contains.rb
301
323
  - test/test_ripe_geocoder.rb