graticule 2.3.0 → 2.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (77) hide show
  1. data/.autotest +13 -0
  2. data/.gitignore +10 -0
  3. data/.travis.yml +14 -0
  4. data/CHANGELOG.txt +4 -1
  5. data/Gemfile +7 -0
  6. data/LICENSE.txt +1 -1
  7. data/README.md +122 -0
  8. data/Rakefile +78 -0
  9. data/graticule.gemspec +26 -0
  10. data/lib/graticule/cli.rb +3 -1
  11. data/lib/graticule/geocoder/google.rb +33 -4
  12. data/lib/graticule/geocoder/mapquest.rb +52 -59
  13. data/lib/graticule/precision.rb +3 -1
  14. data/lib/graticule/version.rb +1 -1
  15. data/site/index.html +114 -0
  16. data/site/plugin.html +82 -0
  17. data/site/stylesheets/style.css +69 -0
  18. data/test/config.yml.default +33 -0
  19. data/test/fixtures/responses/freethepostcode/not_found.txt +3 -0
  20. data/test/fixtures/responses/freethepostcode/success.txt +2 -0
  21. data/test/fixtures/responses/geocoder_ca/success.xml +12 -0
  22. data/test/fixtures/responses/geocoder_us/success.xml +8 -0
  23. data/test/fixtures/responses/geocoder_us/unknown.xml +1 -0
  24. data/test/fixtures/responses/geonames/missing.xml +4 -0
  25. data/test/fixtures/responses/geonames/success.xml +14 -0
  26. data/test/fixtures/responses/geonames/unknown.xml +4 -0
  27. data/test/fixtures/responses/google/address.json +64 -0
  28. data/test/fixtures/responses/google/badkey.json +4 -0
  29. data/test/fixtures/responses/google/country.json +43 -0
  30. data/test/fixtures/responses/google/limit.json +4 -0
  31. data/test/fixtures/responses/google/locality.json +58 -0
  32. data/test/fixtures/responses/google/region.json +48 -0
  33. data/test/fixtures/responses/google/server_error.json +4 -0
  34. data/test/fixtures/responses/google/street.json +58 -0
  35. data/test/fixtures/responses/google/success.json +64 -0
  36. data/test/fixtures/responses/google/success_multiple_results.json +68 -0
  37. data/test/fixtures/responses/google/zero_results.json +4 -0
  38. data/test/fixtures/responses/host_ip/private.txt +4 -0
  39. data/test/fixtures/responses/host_ip/success.txt +4 -0
  40. data/test/fixtures/responses/host_ip/unknown.txt +4 -0
  41. data/test/fixtures/responses/local_search_maps/empty.txt +1 -0
  42. data/test/fixtures/responses/local_search_maps/not_found.txt +1 -0
  43. data/test/fixtures/responses/local_search_maps/success.txt +1 -0
  44. data/test/fixtures/responses/mapquest/multi_result.xml +317 -0
  45. data/test/fixtures/responses/mapquest/success.xml +54 -0
  46. data/test/fixtures/responses/multimap/missing_params.xml +4 -0
  47. data/test/fixtures/responses/multimap/no_matches.xml +4 -0
  48. data/test/fixtures/responses/multimap/success.xml +19 -0
  49. data/test/fixtures/responses/simple_geo/error.json +4 -0
  50. data/test/fixtures/responses/simple_geo/success.json +255 -0
  51. data/test/fixtures/responses/yahoo/success.xml +3 -0
  52. data/test/fixtures/responses/yahoo/unknown_address.xml +6 -0
  53. data/test/fixtures/responses/yandex/badkey.xml +5 -0
  54. data/test/fixtures/responses/yandex/success.xml +204 -0
  55. data/test/graticule/distance_test.rb +59 -0
  56. data/test/graticule/geocoder/freethepostcode_test.rb +37 -0
  57. data/test/graticule/geocoder/geocoder_ca_test.rb +42 -0
  58. data/test/graticule/geocoder/geocoder_us_test.rb +44 -0
  59. data/test/graticule/geocoder/geocoders.rb +56 -0
  60. data/test/graticule/geocoder/geonames_test.rb +56 -0
  61. data/test/graticule/geocoder/google_signed_test.rb +19 -0
  62. data/test/graticule/geocoder/google_test.rb +138 -0
  63. data/test/graticule/geocoder/host_ip_test.rb +41 -0
  64. data/test/graticule/geocoder/local_search_maps_test.rb +31 -0
  65. data/test/graticule/geocoder/mapquest_test.rb +56 -0
  66. data/test/graticule/geocoder/multi_test.rb +52 -0
  67. data/test/graticule/geocoder/multimap_test.rb +53 -0
  68. data/test/graticule/geocoder/simple_geo_test.rb +45 -0
  69. data/test/graticule/geocoder/yahoo_test.rb +50 -0
  70. data/test/graticule/geocoder/yandex_test.rb +42 -0
  71. data/test/graticule/geocoder_test.rb +24 -0
  72. data/test/graticule/location_test.rb +79 -0
  73. data/test/graticule/precision_test.rb +38 -0
  74. data/test/mocks/uri.rb +53 -0
  75. data/test/test_helper.rb +32 -0
  76. metadata +147 -75
  77. data/README.textile +0 -64
@@ -0,0 +1,59 @@
1
+ # encoding: UTF-8
2
+ require 'test_helper'
3
+
4
+ module Graticule
5
+ module Distance
6
+ class DistanceFormulaTest < Test::Unit::TestCase
7
+ EARTH_RADIUS_IN_MILES = 3963.1676
8
+ EARTH_RADIUS_IN_KILOMETERS = 6378.135
9
+
10
+ FORMULAS = [Haversine, Spherical, Vincenty]
11
+
12
+ def test_earth_radius
13
+ assert_equal EARTH_RADIUS_IN_MILES, EARTH_RADIUS[:miles]
14
+ assert_equal EARTH_RADIUS_IN_KILOMETERS, EARTH_RADIUS[:kilometers]
15
+ end
16
+
17
+ def test_distance
18
+ washington_dc = Location.new(:latitude => 38.898748, :longitude => -77.037684)
19
+ chicago = Location.new(:latitude => 41.85, :longitude => -87.65)
20
+
21
+ FORMULAS.each do |formula|
22
+ assert_in_delta formula.distance(washington_dc, chicago), formula.distance(chicago, washington_dc), 0.00001
23
+ assert_in_delta 594.820, formula.distance(washington_dc, chicago), 1.0
24
+ assert_in_delta 594.820, formula.distance(washington_dc, chicago, :miles), 1.0
25
+ assert_in_delta 957.275, formula.distance(washington_dc, chicago, :kilometers), 1.0
26
+ end
27
+ end
28
+
29
+ def test_distance_between_antipodal_points
30
+ # The Vincenty formula will be indeterminant with antipodal points.
31
+ # See http://mathworld.wolfram.com/AntipodalPoints.html
32
+ washington_dc = Location.new(:latitude => 38.898748, :longitude => -77.037684)
33
+ chicago = Location.new(:latitude => 41.85, :longitude => -87.65)
34
+
35
+ # First, test the deltas.
36
+ FORMULAS.each do |formula|
37
+ assert_in_delta 12450.6582171051,
38
+ formula.distance(chicago, chicago.antipodal_location), 1.0
39
+ assert_in_delta 12450.6582171051,
40
+ formula.distance(washington_dc, washington_dc.antipodal_location), 1.0
41
+ assert_in_delta 12450.6582171051,
42
+ formula.distance(chicago, chicago.antipodal_location, :miles), 1.0
43
+ assert_in_delta 12450.6582171051,
44
+ formula.distance(washington_dc, washington_dc.antipodal_location, :miles), 1.0
45
+ assert_in_delta 20037.50205960391,
46
+ formula.distance(chicago, chicago.antipodal_location, :kilometers), 1.0
47
+ assert_in_delta 20037.5020596039,
48
+ formula.distance(washington_dc, washington_dc.antipodal_location, :kilometers), 1.0
49
+ end
50
+
51
+ # Next, test Vincenty. Vincenty will use haversine instead of returning NaN on antipodal points
52
+ assert_equal Haversine.distance(washington_dc, washington_dc.antipodal_location),
53
+ Vincenty.distance(washington_dc, washington_dc.antipodal_location)
54
+ assert_equal Haversine.distance(chicago, chicago.antipodal_location),
55
+ Vincenty.distance(chicago, chicago.antipodal_location)
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,37 @@
1
+ # encoding: UTF-8
2
+ require 'test_helper'
3
+
4
+ module Graticule
5
+ module Geocoder
6
+ class FreeThePostcodeTest < Test::Unit::TestCase
7
+
8
+ def setup
9
+ URI::HTTP.responses = []
10
+ URI::HTTP.uris = []
11
+ @geocoder = FreeThePostcode.new
12
+ end
13
+
14
+ def test_success
15
+ return unless prepare_response(:success)
16
+
17
+ location = Location.new(
18
+ :latitude => 51.503172,
19
+ :longitude => -0.241641)
20
+
21
+ assert_equal location, @geocoder.locate('W1A 1AA')
22
+ end
23
+
24
+ def test_locate_unknown_address
25
+ return unless prepare_response(:not_found)
26
+ assert_raises(AddressError) { @geocoder.locate 'Z12 9pp' }
27
+ end
28
+
29
+ protected
30
+
31
+ def prepare_response(id = :success)
32
+ URI::HTTP.responses << response('freethepostcode', id, 'txt')
33
+ end
34
+
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,42 @@
1
+ # encoding: UTF-8
2
+ require 'test_helper'
3
+
4
+ module Graticule
5
+ module Geocoder
6
+ class GeocoderCaTest < Test::Unit::TestCase
7
+
8
+ def setup
9
+ URI::HTTP.responses = []
10
+ URI::HTTP.uris = []
11
+
12
+ @geocoder = GeocoderCa.new
13
+ @location = Location.new(
14
+ :latitude => 45.418076,
15
+ :longitude => -75.693293,
16
+ :locality => "ottawa",
17
+ :precision => :unknown,
18
+ :region => "ON",
19
+ :street => "200 MUTCALF "
20
+ )
21
+ end
22
+
23
+ def test_success
24
+ prepare_response(:success)
25
+ assert_equal @location, @geocoder.locate('200 mutcalf, ottawa on')
26
+ end
27
+
28
+ def test_url
29
+ prepare_response(:success)
30
+ @geocoder.locate('200 mutcalf, ottawa on')
31
+ assert_equal 'http://geocoder.ca/?geoit=XML&locate=200%20mutcalf,%20ottawa%20on&showpostal=1&standard=1',
32
+ URI::HTTP.uris.first
33
+ end
34
+
35
+ protected
36
+ def prepare_response(id)
37
+ URI::HTTP.responses << response('geocoder_ca', id)
38
+ end
39
+
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,44 @@
1
+ # encoding: UTF-8
2
+ require 'test_helper'
3
+
4
+ module Graticule
5
+ module Geocoder
6
+ class GeocoderUsTest < Test::Unit::TestCase
7
+
8
+ def setup
9
+ URI::HTTP.responses = []
10
+ URI::HTTP.uris = []
11
+
12
+ @geocoder = GeocoderUs.new
13
+ @location = Location.new(
14
+ :street => "1600 Pennsylvania Ave NW, Washington DC 20502",
15
+ :longitude => -77.037684,
16
+ :latitude => 38.898748
17
+ )
18
+ end
19
+
20
+ def test_success
21
+ prepare_response(:success)
22
+ assert_equal @location, @geocoder.locate('1600 Pennsylvania Ave, Washington DC')
23
+ end
24
+
25
+ def test_url
26
+ prepare_response(:success)
27
+ @geocoder.locate('1600 Pennsylvania Ave, Washington DC')
28
+ assert_equal 'http://rpc.geocoder.us/service/rest/geocode?address=1600%20Pennsylvania%20Ave,%20Washington%20DC',
29
+ URI::HTTP.uris.first
30
+ end
31
+
32
+ def test_locate_bad_address
33
+ prepare_response(:unknown)
34
+ assert_raises(AddressError) { @geocoder.locate('yuck') }
35
+ end
36
+
37
+ protected
38
+ def prepare_response(id)
39
+ URI::HTTP.responses << response('geocoder_us', id)
40
+ end
41
+
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,56 @@
1
+ # encoding: UTF-8
2
+ require 'test_helper'
3
+
4
+ module Graticule
5
+
6
+ # Generic tests for all geocoders (theoretically)
7
+ module GeocodersTestCase
8
+
9
+ def test_success
10
+ return unless prepare_response(:success)
11
+
12
+ location = Location.new(
13
+ :street => "1600 Amphitheatre Pkwy",
14
+ :city => "Mountain View",
15
+ :state => "CA",
16
+ :zip => "94043",
17
+ :country => "US",
18
+ :longitude => -122.083739,
19
+ :latitude => 37.423021,
20
+ :precision => :address
21
+ )
22
+ assert_equal location, @geocoder.locate('1600 Amphitheatre Parkway, Mountain View, CA')
23
+ end
24
+
25
+ def test_bad_key
26
+ return unless prepare_response(:badkey)
27
+ assert_raises(CredentialsError) { @geocoder.locate('x') }
28
+ end
29
+
30
+ def test_locate_missing_address
31
+ return unless prepare_response(:missing_address)
32
+ assert_raises(AddressError) { @geocoder.locate 'x' }
33
+ end
34
+
35
+ def test_locate_server_error
36
+ return unless prepare_response(:server_error)
37
+ assert_raises(Error) { @geocoder.locate 'x' }
38
+ end
39
+
40
+ def test_locate_too_many_queries
41
+ return unless prepare_response(:limit)
42
+ assert_raises(CredentialsError) { @geocoder.locate 'x' }
43
+ end
44
+
45
+ def test_locate_unavailable_address
46
+ return unless prepare_response(:unavailable)
47
+ assert_raises(AddressError) { @geocoder.locate 'x' }
48
+ end
49
+
50
+ def test_locate_unknown_address
51
+ return unless prepare_response(:unknown_address)
52
+ assert_raises(AddressError) { @geocoder.locate 'x' }
53
+ end
54
+
55
+ end
56
+ end
@@ -0,0 +1,56 @@
1
+ # encoding: UTF-8
2
+ require 'test_helper'
3
+
4
+ module Graticule
5
+ module Geocoder
6
+ class GeonamesTest < Test::Unit::TestCase
7
+ def setup
8
+ URI::HTTP.responses = []
9
+ URI::HTTP.uris = []
10
+ @geocoder = Geonames.new
11
+ end
12
+
13
+ def test_time_zone
14
+ return unless prepare_response(:success)
15
+
16
+ chicago = Location.new(:latitude => 41.85, :longitude => -87.65)
17
+ assert_equal 'America/Chicago', @geocoder.time_zone(chicago)
18
+ end
19
+
20
+ def test_time_zone
21
+ URI::HTTP.uris = []
22
+ URI::HTTP.responses = []
23
+ URI::HTTP.responses << response('geonames', :success)
24
+ chicago = Location.new(:latitude => 41.85, :longitude => -87.65)
25
+ assert_equal 'America/Chicago', @geocoder.time_zone(chicago)
26
+ end
27
+
28
+ # def test_locate_server_error
29
+ # return unless prepare_response(:server_error)
30
+ # assert_raises(Error) { @geocoder.locate 'x' }
31
+ # end
32
+ #
33
+ # def test_locate_too_many_queries
34
+ # return unless prepare_response(:limit)
35
+ # assert_raises(CredentialsError) { @geocoder.locate 'x' }
36
+ # end
37
+ #
38
+ # def test_locate_unavailable_address
39
+ # return unless prepare_response(:unavailable)
40
+ # assert_raises(AddressError) { @geocoder.locate 'x' }
41
+ # end
42
+ #
43
+ # def test_locate_unknown_address
44
+ # return unless prepare_response(:unknown_address)
45
+ # assert_raises(AddressError) { @geocoder.locate 'x' }
46
+ # end
47
+
48
+ protected
49
+
50
+ def prepare_response(id = :success)
51
+ URI::HTTP.responses << response('geonames', id)
52
+ end
53
+
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,19 @@
1
+ # encoding: UTF-8
2
+ require 'test_helper'
3
+
4
+ class GoogleTest < Test::Unit::TestCase
5
+ def test_url_is_signed_for_business_accounts
6
+ geocoder = Graticule.service(:google).new("e7-fake-account-R911GuLecpVqA=", 'gme-example')
7
+ url = geocoder.send :make_url, :address => 'New York'
8
+ expected = "http://maps.googleapis.com/maps/api/geocode/json?address=New%20York&client=gme-example&sensor=false&signature=EJNTEh9SqstO1FLcbFsQ0aJrWHA="
9
+ assert_equal expected, url.to_s
10
+ end
11
+
12
+ def test_url_is_not_signed_for_normal_accounts
13
+ geocoder = Graticule.service(:google).new()
14
+ url = geocoder.send :make_url, :address => 'New York'
15
+ expected = "http://maps.googleapis.com/maps/api/geocode/json?address=New%20York&sensor=false"
16
+ assert_equal expected, url.to_s
17
+ end
18
+ end
19
+
@@ -0,0 +1,138 @@
1
+ # encoding: UTF-8
2
+ require 'test_helper'
3
+
4
+ module Graticule
5
+ module Geocoder
6
+ class GoogleTest < Test::Unit::TestCase
7
+ def setup
8
+ URI::HTTP.responses = []
9
+ URI::HTTP.uris = []
10
+ @geocoder = Google.new('APP_ID')
11
+ end
12
+
13
+ def test_success
14
+ return unless prepare_response(:success)
15
+ location = Location.new(
16
+ :latitude=>37.421641,
17
+ :longitude=>-122.0855016,
18
+ :street=>"1600 Amphitheatre Pkwy",
19
+ :locality=>"Mountain View",
20
+ :region=>"CA",
21
+ :postal_code=>"94043",
22
+ :country=>"US",
23
+ :precision=>:address
24
+ )
25
+ assert_equal location, @geocoder.locate('1600 Amphitheatre Parkway, Mountain View, CA')
26
+ end
27
+
28
+ # The #locate parameters are broad, so the JSON response contains
29
+ # multiple results at street-level precision. We expect to get the
30
+ # first result back, and it should not contain a postal code.
31
+ def test_success_multiple_results
32
+ return unless prepare_response(:success_multiple_results)
33
+ location = Location.new(
34
+ :latitude=>43.645337,
35
+ :longitude=>-79.413208,
36
+ :street=>"Queen St W",
37
+ :locality=>"Toronto",
38
+ :region=>"ON",
39
+ :country=>"CA",
40
+ :precision=>:street
41
+ )
42
+ assert_equal location, @geocoder.locate('Queen St West, Toronto, ON CA')
43
+ end
44
+
45
+ def test_precision_region
46
+ return unless prepare_response(:region)
47
+ location = Location.new(
48
+ :latitude=> 36.7782610,
49
+ :longitude=>-119.41793240,
50
+ :region=>"CA",
51
+ :country=>"US",
52
+ :precision=>:region
53
+ )
54
+ assert_equal location, @geocoder.locate('CA US')
55
+ end
56
+
57
+ def test_precision_country
58
+ return unless prepare_response(:country)
59
+ location = Location.new(
60
+ :latitude=>37.090240,
61
+ :longitude=>-95.7128910,
62
+ :country=>"US",
63
+ :precision=>:country
64
+ )
65
+ assert_equal location, @geocoder.locate('US')
66
+ end
67
+
68
+ def test_precision_locality
69
+ return unless prepare_response(:locality)
70
+ location = Location.new(
71
+ :latitude=>37.7749295,
72
+ :longitude=>-122.4194155,
73
+ :country=>"US",
74
+ :region=>"CA",
75
+ :locality=>"San Francisco",
76
+ :precision=>:locality
77
+ )
78
+ assert_equal location, @geocoder.locate('San Francisco, CA US')
79
+ end
80
+
81
+ def test_precision_street
82
+ return unless prepare_response(:street)
83
+ location = Location.new(
84
+ :latitude=>37.42325960000001,
85
+ :longitude=>-122.08563830,
86
+ :country=>"US",
87
+ :region=>"CA",
88
+ :street=>"Amphitheatre Pkwy",
89
+ :locality=>"Mountain View",
90
+ :precision=>:street
91
+ )
92
+ assert_equal location, @geocoder.locate('Amphitheatre Pkwy, Mountain View CA US')
93
+ end
94
+
95
+ def test_precision_address
96
+ return unless prepare_response(:address)
97
+ location = Location.new(
98
+ :latitude=>37.421641,
99
+ :longitude=>-122.0855016,
100
+ :street=>"1600 Amphitheatre Pkwy",
101
+ :locality=>"Mountain View",
102
+ :region=>"CA",
103
+ :postal_code=>"94043",
104
+ :country=>"US",
105
+ :precision=>:address
106
+ )
107
+ assert_equal location, @geocoder.locate('1600 Amphitheatre Parkway, Mountain View, CA')
108
+ end
109
+
110
+ def test_locate_server_error
111
+ return unless prepare_response(:server_error)
112
+ assert_raises(Error) { @geocoder.locate 'x' }
113
+ end
114
+
115
+ def test_locate_too_many_queries
116
+ return unless prepare_response(:limit)
117
+ assert_raises(CredentialsError) { @geocoder.locate 'x' }
118
+ end
119
+
120
+ def test_locate_zero_results
121
+ return unless prepare_response(:zero_results)
122
+ assert_raises(AddressError) { @geocoder.locate 'x' }
123
+ end
124
+
125
+ def test_bad_key
126
+ return unless prepare_response(:badkey)
127
+ assert_raises(CredentialsError) { @geocoder.locate('x') }
128
+ end
129
+
130
+ protected
131
+
132
+ def prepare_response(id = :success)
133
+ URI::HTTP.responses << response('google', id, 'json')
134
+ end
135
+
136
+ end
137
+ end
138
+ end