geocoder 1.2.5 → 1.2.6

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.

Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +7 -0
  3. data/README.md +83 -8
  4. data/lib/geocoder/ip_address.rb +11 -2
  5. data/lib/geocoder/lookup.rb +4 -0
  6. data/lib/geocoder/lookups/geoip2.rb +40 -0
  7. data/lib/geocoder/lookups/google_places_details.rb +50 -0
  8. data/lib/geocoder/lookups/maxmind_local.rb +1 -1
  9. data/lib/geocoder/lookups/okf.rb +43 -0
  10. data/lib/geocoder/lookups/postcode_anywhere_uk.rb +51 -0
  11. data/lib/geocoder/lookups/smarty_streets.rb +1 -1
  12. data/lib/geocoder/results/geoip2.rb +64 -0
  13. data/lib/geocoder/results/google_places_details.rb +35 -0
  14. data/lib/geocoder/results/okf.rb +106 -0
  15. data/lib/geocoder/results/postcode_anywhere_uk.rb +42 -0
  16. data/lib/geocoder/results/test.rb +1 -1
  17. data/lib/geocoder/stores/active_record.rb +22 -11
  18. data/lib/geocoder/version.rb +1 -1
  19. data/test/fixtures/google_places_details_invalid_request +4 -0
  20. data/test/fixtures/google_places_details_madison_square_garden +120 -0
  21. data/test/fixtures/google_places_details_no_results +4 -0
  22. data/test/fixtures/google_places_details_no_reviews +60 -0
  23. data/test/fixtures/google_places_details_no_types +66 -0
  24. data/test/fixtures/okf_kirstinmaki +67 -0
  25. data/test/fixtures/okf_no_results +4 -0
  26. data/test/fixtures/postcode_anywhere_uk_geocode_v2_00_WR26NJ +1 -0
  27. data/test/fixtures/postcode_anywhere_uk_geocode_v2_00_generic_error +1 -0
  28. data/test/fixtures/postcode_anywhere_uk_geocode_v2_00_hampshire +1 -0
  29. data/test/fixtures/postcode_anywhere_uk_geocode_v2_00_key_limit_exceeded +1 -0
  30. data/test/fixtures/postcode_anywhere_uk_geocode_v2_00_no_results +1 -0
  31. data/test/fixtures/postcode_anywhere_uk_geocode_v2_00_romsey +1 -0
  32. data/test/fixtures/postcode_anywhere_uk_geocode_v2_00_unknown_key +1 -0
  33. data/test/test_helper.rb +44 -0
  34. data/test/unit/cache_test.rb +1 -1
  35. data/test/unit/error_handling_test.rb +3 -3
  36. data/test/unit/ip_address_test.rb +3 -0
  37. data/test/unit/lookup_test.rb +1 -1
  38. data/test/unit/lookups/geoip2_test.rb +27 -0
  39. data/test/unit/lookups/google_places_details_test.rb +122 -0
  40. data/test/unit/lookups/okf_test.rb +38 -0
  41. data/test/unit/lookups/postcode_anywhere_uk_test.rb +70 -0
  42. data/test/unit/query_test.rb +1 -0
  43. data/test/unit/test_mode_test.rb +1 -1
  44. metadata +28 -2
@@ -0,0 +1,66 @@
1
+ {
2
+ "html_attributions" : [],
3
+ "result" : {
4
+ "address_components" : [
5
+ {
6
+ "long_name" : "6",
7
+ "short_name" : "6",
8
+ "types" : [ "street_number" ]
9
+ },
10
+ {
11
+ "long_name" : "Graniczna",
12
+ "short_name" : "Graniczna",
13
+ "types" : [ "route" ]
14
+ },
15
+ {
16
+ "long_name" : "Gdynia",
17
+ "short_name" : "Gdynia",
18
+ "types" : [ "locality", "political" ]
19
+ },
20
+ {
21
+ "long_name" : "Gdynia",
22
+ "short_name" : "Gdynia",
23
+ "types" : [ "administrative_area_level_3", "political" ]
24
+ },
25
+ {
26
+ "long_name" : "Gdynia",
27
+ "short_name" : "Gdynia",
28
+ "types" : [ "administrative_area_level_2", "political" ]
29
+ },
30
+ {
31
+ "long_name" : "Pomeranian Voivodeship",
32
+ "short_name" : "Pomeranian Voivodeship",
33
+ "types" : [ "administrative_area_level_1", "political" ]
34
+ },
35
+ {
36
+ "long_name" : "Poland",
37
+ "short_name" : "PL",
38
+ "types" : [ "country", "political" ]
39
+ },
40
+ {
41
+ "long_name" : "81-626",
42
+ "short_name" : "81-626",
43
+ "types" : [ "postal_code" ]
44
+ }
45
+ ],
46
+ "adr_address" : "\u003cspan class=\"street-address\"\u003eGraniczna 6\u003c/span\u003e, \u003cspan class=\"postal-code\"\u003e81-626\u003c/span\u003e \u003cspan class=\"locality\"\u003eGdynia\u003c/span\u003e, \u003cspan class=\"country-name\"\u003ePoland\u003c/span\u003e",
47
+ "formatted_address" : "Graniczna 6, Gdynia, Poland",
48
+ "formatted_phone_number" : "795 085 050",
49
+ "geometry" : {
50
+ "location" : {
51
+ "lat" : 54.493608,
52
+ "lng" : 18.508983
53
+ }
54
+ },
55
+ "id" : "aed47c412bce35bb385c86edef64f8f7860b1cf8",
56
+ "international_phone_number" : "+48 795 085 050",
57
+ "name" : "Taxi Gdynia",
58
+ "place_id" : "ChIJgT2H0tig_UYRD9iM2NSOo4Y",
59
+ "reference" : "CnRlAAAA6bzgakKCXzwjtLBSMLvj0fvv3OSwGp2WsA54VwQELEupFzqtFuUmxMyMSNYt745EukJR0Ui6Ih9WX3AdL--HXjQprE8xHSb_6qQh2eauKWFIoHzIvbMrkjDIcUPxPDMdJc2XkwpOr_EUimZplCy-gBIQb_UHtRVaswAMjdHHtDqzURoU3tGbILe-zhN3oISBAvc3AyoyznE",
60
+ "scope" : "GOOGLE",
61
+ "url" : "https://plus.google.com/100174651414421384172/about?hl=en-US",
62
+ "utc_offset" : 120,
63
+ "vicinity" : "Graniczna 6, Gdynia"
64
+ },
65
+ "status" : "OK"
66
+ }
@@ -0,0 +1,67 @@
1
+ {
2
+ "status" : "OK",
3
+ "results" : [
4
+ {
5
+ "formatted_address" : "Kirstinmäki 1, 02760 Espoo, Suomi",
6
+ "sources" : [
7
+ {
8
+ "name" : "National Land Survey of Finland - Topographic Dataset (2013-03-08)",
9
+ "terms_of_use" : "National Land Survey open data licence - version 1.0 - 1 May 2012\nhttp://www.maanmittauslaitos.fi/en/NLS_open_data_licence_version1_20120501"
10
+ },
11
+ {
12
+ "name" : "Itella perusosoitteisto (2014-02-01)",
13
+ "terms_of_use" : "http://www.itella.fi/liitteet/palvelutjatuotteet/yhteystietopalvelut/Postinumeropalvelut-Palvelukuvausjakayttoehdot.pdf"
14
+ }
15
+ ],
16
+ "types" : [
17
+ "street_address"
18
+ ],
19
+ "address_components" : [
20
+ {
21
+ "types" : [
22
+ "street_number"
23
+ ],
24
+ "short_name" : "1",
25
+ "long_name" : "1"
26
+ },
27
+ {
28
+ "types" : [
29
+ "route"
30
+ ],
31
+ "short_name" : "Kirstinmäki",
32
+ "long_name" : "Kirstinmäki"
33
+ },
34
+ {
35
+ "types" : [
36
+ "administrative_area_level_3",
37
+ "political"
38
+ ],
39
+ "short_name" : "Espoo",
40
+ "long_name" : "Espoo"
41
+ },
42
+ {
43
+ "types" : [
44
+ "postal_code"
45
+ ],
46
+ "short_name" : "02760",
47
+ "long_name" : "02760"
48
+ },
49
+ {
50
+ "types" : [
51
+ "country",
52
+ "political"
53
+ ],
54
+ "short_name" : "FI",
55
+ "long_name" : "Suomi"
56
+ }
57
+ ],
58
+ "geometry" : {
59
+ "location" : {
60
+ "lat" : 60.2015185792087,
61
+ "lng" : 24.6667520050026
62
+ },
63
+ "location_type" : "RANGE_INTERPOLATED"
64
+ }
65
+ }
66
+ ]
67
+ }
@@ -0,0 +1,4 @@
1
+ {
2
+ "status" : "ZERO_RESULTS",
3
+ "results" : []
4
+ }
@@ -0,0 +1 @@
1
+ [{"Location":"Moseley Road, Hallow, Worcester","Easting":"381676","Northing":"259425","Latitude":"52.2327","Longitude":"-2.2697","OsGrid":"SO 81676 59425","Accuracy":"Standard"}]
@@ -0,0 +1 @@
1
+ [{"Error":"9999","Description":"A generic error","Cause":"A generic error occured.","Resolution":"Fix the unknown error."}]
@@ -0,0 +1 @@
1
+ [{"Location":"Hampshire","Easting":"448701","Northing":"126642","Latitude":"51.037","Longitude":"-1.3068","OsGrid":"SU 48701 26642","Accuracy":"Standard"}]
@@ -0,0 +1 @@
1
+ [{"Error":"8","Description":"Key daily limit exceeded","Cause":"The daily limit on the key has been exceeded.","Resolution":"Alter the daily limit on the key. Check the usage details first to see if usage is normal."}]
@@ -0,0 +1 @@
1
+ [{"Location":"Romsey, Hampshire","Easting":"435270","Northing":"121182","Latitude":"50.9889","Longitude":"-1.4989","OsGrid":"SU 35270 21182","Accuracy":"Standard"}]
@@ -0,0 +1 @@
1
+ [{"Error":"2","Description":"Unknown key","Cause":"The key you are using to access the service was not found.","Resolution":"Please check that the key is correct. It should be in the form AA11-AA11-AA11-AA11."}]
data/test/test_helper.rb CHANGED
@@ -122,6 +122,13 @@ module Geocoder
122
122
  end
123
123
  end
124
124
 
125
+ class GooglePlacesDetails
126
+ private
127
+ def fixture_prefix
128
+ "google_places_details"
129
+ end
130
+ end
131
+
125
132
  class Dstk
126
133
  private
127
134
  def fixture_prefix
@@ -143,6 +150,25 @@ module Geocoder
143
150
  end
144
151
  end
145
152
 
153
+ class Geoip2
154
+ private
155
+
156
+ remove_method(:results)
157
+
158
+ def results(query)
159
+ return [] if query.to_s == 'no results'
160
+ return [] if query.to_s == '127.0.0.1'
161
+ [{'city'=>{'names'=>{'en'=>'Mountain View'}},'country'=>{'iso_code'=>'US','names'=>
162
+ {'en'=>'United States'}},'location'=>{'latitude'=>37.41919999999999,
163
+ 'longitude'=>-122.0574},'postal'=>{'code'=>'94043'},'subdivisions'=>[{
164
+ 'iso_code'=>'CA','names'=>{'en'=>'California'}}]}]
165
+ end
166
+
167
+ def default_fixture_filename
168
+ 'geoip2_74_200_247_59'
169
+ end
170
+ end
171
+
146
172
  class Telize
147
173
  private
148
174
  def default_fixture_filename
@@ -200,6 +226,24 @@ module Geocoder
200
226
  "geocodio_1101_pennsylvania_ave"
201
227
  end
202
228
  end
229
+
230
+ class Okf
231
+ private
232
+ def default_fixture_filename
233
+ "okf_kirstinmaki"
234
+ end
235
+ end
236
+
237
+ class PostcodeAnywhereUk
238
+ private
239
+ def fixture_prefix
240
+ 'postcode_anywhere_uk_geocode_v2_00'
241
+ end
242
+
243
+ def default_fixture_filename
244
+ "#{fixture_prefix}_romsey"
245
+ end
246
+ end
203
247
  end
204
248
  end
205
249
 
@@ -7,7 +7,7 @@ class CacheTest < GeocoderTestCase
7
7
  def test_second_occurrence_of_request_is_cache_hit
8
8
  Geocoder.configure(:cache => {})
9
9
  Geocoder::Lookup.all_services_except_test.each do |l|
10
- next if l == :maxmind_local # local, does not use cache
10
+ next if l == :maxmind_local || l == :geoip2 # local, does not use cache
11
11
  Geocoder.configure(:lookup => l)
12
12
  set_api_key!(l)
13
13
  results = Geocoder.search("Madison Square Garden")
@@ -21,7 +21,7 @@ class ErrorHandlingTest < GeocoderTestCase
21
21
  def test_always_raise_timeout_error
22
22
  Geocoder.configure(:always_raise => [TimeoutError])
23
23
  Geocoder::Lookup.all_services_except_test.each do |l|
24
- next if l == :maxmind_local # local, does not raise timeout
24
+ next if l == :maxmind_local || l == :geoip2 # local, does not use cache
25
25
  lookup = Geocoder::Lookup.get(l)
26
26
  set_api_key!(l)
27
27
  assert_raises TimeoutError do
@@ -33,7 +33,7 @@ class ErrorHandlingTest < GeocoderTestCase
33
33
  def test_always_raise_socket_error
34
34
  Geocoder.configure(:always_raise => [SocketError])
35
35
  Geocoder::Lookup.all_services_except_test.each do |l|
36
- next if l == :maxmind_local # local, does not raise timeout
36
+ next if l == :maxmind_local || l == :geoip2 # local, does not use cache
37
37
  lookup = Geocoder::Lookup.get(l)
38
38
  set_api_key!(l)
39
39
  assert_raises SocketError do
@@ -45,7 +45,7 @@ class ErrorHandlingTest < GeocoderTestCase
45
45
  def test_always_raise_connection_refused_error
46
46
  Geocoder.configure(:always_raise => [Errno::ECONNREFUSED])
47
47
  Geocoder::Lookup.all_services_except_test.each do |l|
48
- next if l == :maxmind_local # local, does not raise timeout
48
+ next if l == :maxmind_local || l == :geoip2 # local, does not use cache
49
49
  lookup = Geocoder::Lookup.get(l)
50
50
  set_api_key!(l)
51
51
  assert_raises Errno::ECONNREFUSED do
@@ -8,6 +8,8 @@ class IpAddressTest < GeocoderTestCase
8
8
  assert Geocoder::IpAddress.new("232.65.123.94").valid?
9
9
  assert Geocoder::IpAddress.new("666.65.123.94").valid? # technically invalid
10
10
  assert Geocoder::IpAddress.new("::ffff:12.34.56.78").valid?
11
+ assert Geocoder::IpAddress.new("3ffe:0b00:0000:0000:0001:0000:0000:000a").valid?
12
+ assert Geocoder::IpAddress.new("::1").valid?
11
13
  assert !Geocoder::IpAddress.new("232.65.123.94.43").valid?
12
14
  assert !Geocoder::IpAddress.new("232.65.123").valid?
13
15
  assert !Geocoder::IpAddress.new("::ffff:123.456.789").valid?
@@ -17,6 +19,7 @@ class IpAddressTest < GeocoderTestCase
17
19
  def test_loopback
18
20
  assert Geocoder::IpAddress.new("0.0.0.0").loopback?
19
21
  assert Geocoder::IpAddress.new("127.0.0.1").loopback?
22
+ assert Geocoder::IpAddress.new("::1").loopback?
20
23
  assert !Geocoder::IpAddress.new("232.65.123.234").loopback?
21
24
  assert !Geocoder::IpAddress.new("127 Main St.").loopback?
22
25
  assert !Geocoder::IpAddress.new("John Doe\n127 Main St.\nAnywhere, USA").loopback?
@@ -23,7 +23,7 @@ class LookupTest < GeocoderTestCase
23
23
 
24
24
  def test_query_url_contains_values_in_params_hash
25
25
  Geocoder::Lookup.all_services_except_test.each do |l|
26
- next if [:freegeoip, :maxmind_local, :telize, :pointpin].include? l # does not use query string
26
+ next if [:freegeoip, :maxmind_local, :telize, :pointpin, :geoip2].include? l # does not use query string
27
27
  set_api_key!(l)
28
28
  url = Geocoder::Lookup.get(l).query_url(Geocoder::Query.new(
29
29
  "test", :params => {:one_in_the_hand => "two in the bush"}
@@ -0,0 +1,27 @@
1
+ # encoding: utf-8
2
+ require 'test_helper'
3
+
4
+ class Geoip2Test < GeocoderTestCase
5
+ def setup
6
+ Geocoder.configure(ip_lookup: :geoip2, file: 'test_file')
7
+ end
8
+
9
+ def test_result_attributes
10
+ result = Geocoder.search('8.8.8.8').first
11
+ assert_equal 'Mountain View, CA 94043, United States', result.address
12
+ assert_equal 'Mountain View', result.city
13
+ assert_equal 'CA', result.state_code
14
+ assert_equal 'California', result.state
15
+ assert_equal 'United States', result.country
16
+ assert_equal 'US', result.country_code
17
+ assert_equal '94043', result.postal_code
18
+ assert_equal 37.41919999999999, result.latitude
19
+ assert_equal -122.0574, result.longitude
20
+ assert_equal [37.41919999999999, -122.0574], result.coordinates
21
+ end
22
+
23
+ def test_loopback
24
+ results = Geocoder.search('127.0.0.1')
25
+ assert_equal [], results
26
+ end
27
+ end
@@ -0,0 +1,122 @@
1
+ # encoding: utf-8
2
+ $: << File.join(File.dirname(__FILE__), "..", "..")
3
+ require 'test_helper'
4
+
5
+ class GooglePlacesDetailsTest < GeocoderTestCase
6
+
7
+ def setup
8
+ Geocoder.configure(lookup: :google_places_details)
9
+ set_api_key!(:google_places_details)
10
+ end
11
+
12
+ def test_google_places_details_result_components
13
+ assert_equal "Manhattan", madison_square_garden.address_components_of_type(:sublocality).first["long_name"]
14
+ end
15
+
16
+ def test_google_places_details_result_components_contains_route
17
+ assert_equal "Pennsylvania Plaza", madison_square_garden.address_components_of_type(:route).first["long_name"]
18
+ end
19
+
20
+ def test_google_places_details_result_components_contains_street_number
21
+ assert_equal "4", madison_square_garden.address_components_of_type(:street_number).first["long_name"]
22
+ end
23
+
24
+ def test_google_places_details_street_address_returns_formatted_street_address
25
+ assert_equal "4 Pennsylvania Plaza", madison_square_garden.street_address
26
+ end
27
+
28
+ def test_google_places_details_result_contains_place_id
29
+ assert_equal "ChIJhRwB-yFawokR5Phil-QQ3zM", madison_square_garden.place_id
30
+ end
31
+
32
+ def test_google_places_details_result_contains_latitude
33
+ assert_equal madison_square_garden.latitude, 40.750504
34
+ end
35
+
36
+ def test_google_places_details_result_contains_longitude
37
+ assert_equal madison_square_garden.longitude, -73.993439
38
+ end
39
+
40
+ def test_google_places_details_result_contains_rating
41
+ assert_equal 4.4, madison_square_garden.rating
42
+ end
43
+
44
+ def test_google_places_details_result_contains_rating_count
45
+ assert_equal 382, madison_square_garden.rating_count
46
+ end
47
+
48
+ def test_google_places_details_result_contains_reviews
49
+ reviews = madison_square_garden.reviews
50
+
51
+ assert_equal 2, reviews.size
52
+ assert_equal "John Smith", reviews.first["author_name"]
53
+ assert_equal 5, reviews.first["rating"]
54
+ assert_equal "It's nice.", reviews.first["text"]
55
+ assert_equal "en", reviews.first["language"]
56
+ end
57
+
58
+ def test_google_places_details_result_contains_types
59
+ assert_equal madison_square_garden.types, %w(stadium establishment)
60
+ end
61
+
62
+ def test_google_places_details_result_contains_website
63
+ assert_equal madison_square_garden.website, "http://www.thegarden.com/"
64
+ end
65
+
66
+ def test_google_places_details_result_contains_phone_number
67
+ assert_equal madison_square_garden.phone_number, "+1 212-465-6741"
68
+ end
69
+
70
+ def test_google_places_details_query_url_contains_placeid
71
+ url = lookup.query_url(Geocoder::Query.new("some-place-id"))
72
+ assert_match(/placeid=some-place-id/, url)
73
+ end
74
+
75
+ def test_google_places_details_query_url_contains_language
76
+ url = lookup.query_url(Geocoder::Query.new("some-place-id", language: "de"))
77
+ assert_match(/language=de/, url)
78
+ end
79
+
80
+ def test_google_places_details_query_url_always_uses_https
81
+ url = lookup.query_url(Geocoder::Query.new("some-place-id"))
82
+ assert_match(%r(^https://), url)
83
+ end
84
+
85
+ def test_google_places_details_result_with_no_reviews_shows_empty_reviews
86
+ assert_equal no_reviews_result.reviews, []
87
+ end
88
+
89
+ def test_google_places_details_result_with_no_types_shows_empty_types
90
+ assert_equal no_types_result.types, []
91
+ end
92
+
93
+ def test_google_places_details_result_with_invalid_place_id_empty
94
+ assert_equal Geocoder.search("invalid request"), []
95
+ end
96
+
97
+ def test_raises_exception_on_google_places_details_invalid_request
98
+ Geocoder.configure(always_raise: [Geocoder::InvalidRequest])
99
+ assert_raises Geocoder::InvalidRequest do
100
+ Geocoder.search("invalid request")
101
+ end
102
+ end
103
+
104
+ private
105
+
106
+ def lookup
107
+ Geocoder::Lookup::GooglePlacesDetails.new
108
+ end
109
+
110
+ def madison_square_garden
111
+ Geocoder.search("ChIJhRwB-yFawokR5Phil-QQ3zM").first
112
+ end
113
+
114
+ def no_reviews_result
115
+ Geocoder.search("no reviews").first
116
+ end
117
+
118
+ def no_types_result
119
+ Geocoder.search("no types").first
120
+ end
121
+
122
+ end
@@ -0,0 +1,38 @@
1
+ # encoding: utf-8
2
+ $: << File.join(File.dirname(__FILE__), "..", "..")
3
+ require 'test_helper'
4
+
5
+ class OkfTest < GeocoderTestCase
6
+
7
+ def setup
8
+ Geocoder.configure(lookup: :okf)
9
+ end
10
+
11
+ def test_okf_result_components
12
+ result = Geocoder.search("Kirstinmäki 11b28").first
13
+ assert_equal "Espoo",
14
+ result.address_components_of_type(:administrative_area_level_3).first['long_name']
15
+ end
16
+
17
+ def test_okf_result_components_contains_route
18
+ result = Geocoder.search("Kirstinmäki 11b28").first
19
+ assert_equal "Kirstinmäki",
20
+ result.address_components_of_type(:route).first['long_name']
21
+ end
22
+
23
+ def test_okf_result_components_contains_street_number
24
+ result = Geocoder.search("Kirstinmäki 11b28").first
25
+ assert_equal "1",
26
+ result.address_components_of_type(:street_number).first['long_name']
27
+ end
28
+
29
+ def test_okf_street_address_returns_formatted_street_address
30
+ result = Geocoder.search("Kirstinmäki 11b28").first
31
+ assert_equal "Kirstinmäki 1", result.street_address
32
+ end
33
+
34
+ def test_okf_precision
35
+ result = Geocoder.search("Kirstinmäki 11b28").first
36
+ assert_equal "RANGE_INTERPOLATED", result.precision
37
+ end
38
+ end