graticule 2.3.0 → 2.4.0

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.
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