geokit 1.8.3 → 1.8.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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