geocoder 1.1.9 → 1.3.7

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 (174) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +157 -0
  3. data/README.md +467 -70
  4. data/examples/reverse_geocode_job.rb +40 -0
  5. data/lib/generators/geocoder/config/templates/initializer.rb +16 -16
  6. data/lib/generators/geocoder/maxmind/geolite_city_generator.rb +28 -0
  7. data/lib/generators/geocoder/maxmind/geolite_country_generator.rb +28 -0
  8. data/lib/generators/geocoder/maxmind/templates/migration/geolite_city.rb +30 -0
  9. data/lib/generators/geocoder/maxmind/templates/migration/geolite_country.rb +17 -0
  10. data/lib/geocoder/cache.rb +3 -2
  11. data/lib/geocoder/calculations.rb +44 -2
  12. data/lib/geocoder/configuration.rb +17 -10
  13. data/lib/geocoder/esri_token.rb +38 -0
  14. data/lib/geocoder/exceptions.rb +19 -0
  15. data/lib/geocoder/ip_address.rb +13 -0
  16. data/lib/geocoder/kernel_logger.rb +25 -0
  17. data/lib/geocoder/logger.rb +47 -0
  18. data/lib/geocoder/lookup.rb +32 -8
  19. data/lib/geocoder/lookups/baidu.rb +18 -13
  20. data/lib/geocoder/lookups/baidu_ip.rb +59 -0
  21. data/lib/geocoder/lookups/base.rb +81 -19
  22. data/lib/geocoder/lookups/bing.rb +40 -7
  23. data/lib/geocoder/lookups/esri.rb +42 -5
  24. data/lib/geocoder/lookups/freegeoip.rb +9 -1
  25. data/lib/geocoder/lookups/geocoder_ca.rb +1 -2
  26. data/lib/geocoder/lookups/geocoder_us.rb +6 -2
  27. data/lib/geocoder/lookups/geocodio.rb +42 -0
  28. data/lib/geocoder/lookups/geoip2.rb +45 -0
  29. data/lib/geocoder/lookups/geoportail_lu.rb +65 -0
  30. data/lib/geocoder/lookups/google.rb +29 -5
  31. data/lib/geocoder/lookups/google_places_details.rb +50 -0
  32. data/lib/geocoder/lookups/google_premier.rb +1 -1
  33. data/lib/geocoder/lookups/here.rb +62 -0
  34. data/lib/geocoder/lookups/ipapi_com.rb +86 -0
  35. data/lib/geocoder/lookups/ipinfo_io.rb +55 -0
  36. data/lib/geocoder/lookups/latlon.rb +59 -0
  37. data/lib/geocoder/lookups/mapbox.rb +53 -0
  38. data/lib/geocoder/lookups/mapquest.rb +6 -6
  39. data/lib/geocoder/lookups/mapzen.rb +15 -0
  40. data/lib/geocoder/lookups/maxmind.rb +4 -2
  41. data/lib/geocoder/lookups/maxmind_geoip2.rb +69 -0
  42. data/lib/geocoder/lookups/maxmind_local.rb +65 -0
  43. data/lib/geocoder/lookups/nominatim.rb +9 -1
  44. data/lib/geocoder/lookups/okf.rb +44 -0
  45. data/lib/geocoder/lookups/opencagedata.rb +58 -0
  46. data/lib/geocoder/lookups/pelias.rb +64 -0
  47. data/lib/geocoder/lookups/pointpin.rb +68 -0
  48. data/lib/geocoder/lookups/postcode_anywhere_uk.rb +51 -0
  49. data/lib/geocoder/lookups/smarty_streets.rb +53 -0
  50. data/lib/geocoder/lookups/telize.rb +55 -0
  51. data/lib/geocoder/lookups/yandex.rb +8 -4
  52. data/lib/geocoder/models/active_record.rb +7 -3
  53. data/lib/geocoder/models/base.rb +1 -4
  54. data/lib/geocoder/models/mongo_base.rb +6 -4
  55. data/lib/geocoder/query.rb +9 -5
  56. data/lib/geocoder/railtie.rb +1 -1
  57. data/lib/geocoder/request.rb +74 -12
  58. data/lib/geocoder/results/baidu_ip.rb +62 -0
  59. data/lib/geocoder/results/bing.rb +4 -0
  60. data/lib/geocoder/results/esri.rb +30 -6
  61. data/lib/geocoder/results/freegeoip.rb +2 -2
  62. data/lib/geocoder/results/geocodio.rb +70 -0
  63. data/lib/geocoder/results/geoip2.rb +62 -0
  64. data/lib/geocoder/results/geoportail_lu.rb +69 -0
  65. data/lib/geocoder/results/google.rb +15 -0
  66. data/lib/geocoder/results/google_places_details.rb +35 -0
  67. data/lib/geocoder/results/here.rb +71 -0
  68. data/lib/geocoder/results/ipapi_com.rb +45 -0
  69. data/lib/geocoder/results/ipinfo_io.rb +48 -0
  70. data/lib/geocoder/results/latlon.rb +71 -0
  71. data/lib/geocoder/results/mapbox.rb +47 -0
  72. data/lib/geocoder/results/mapquest.rb +5 -8
  73. data/lib/geocoder/results/mapzen.rb +5 -0
  74. data/lib/geocoder/results/maxmind_geoip2.rb +9 -0
  75. data/lib/geocoder/results/maxmind_local.rb +49 -0
  76. data/lib/geocoder/results/nominatim.rb +6 -1
  77. data/lib/geocoder/results/okf.rb +106 -0
  78. data/lib/geocoder/results/opencagedata.rb +90 -0
  79. data/lib/geocoder/results/ovi.rb +9 -0
  80. data/lib/geocoder/results/pelias.rb +58 -0
  81. data/lib/geocoder/results/pointpin.rb +40 -0
  82. data/lib/geocoder/results/postcode_anywhere_uk.rb +42 -0
  83. data/lib/geocoder/results/smarty_streets.rb +106 -0
  84. data/lib/geocoder/results/telize.rb +45 -0
  85. data/lib/geocoder/results/test.rb +20 -3
  86. data/lib/geocoder/results/yandex.rb +18 -6
  87. data/lib/geocoder/sql.rb +16 -15
  88. data/lib/geocoder/stores/active_record.rb +51 -18
  89. data/lib/geocoder/stores/base.rb +8 -12
  90. data/lib/geocoder/stores/mongo_base.rb +0 -31
  91. data/lib/geocoder/version.rb +1 -1
  92. data/lib/geocoder.rb +6 -13
  93. data/lib/maxmind_database.rb +109 -0
  94. data/lib/tasks/geocoder.rake +14 -3
  95. data/lib/tasks/maxmind.rake +73 -0
  96. metadata +59 -85
  97. data/.gitignore +0 -5
  98. data/.travis.yml +0 -27
  99. data/Rakefile +0 -25
  100. data/gemfiles/Gemfile.mongoid-2.4.x +0 -15
  101. data/lib/geocoder/lookups/yahoo.rb +0 -86
  102. data/lib/geocoder/results/yahoo.rb +0 -55
  103. data/lib/oauth_util.rb +0 -112
  104. data/test/active_record_test.rb +0 -15
  105. data/test/cache_test.rb +0 -35
  106. data/test/calculations_test.rb +0 -211
  107. data/test/configuration_test.rb +0 -78
  108. data/test/custom_block_test.rb +0 -32
  109. data/test/error_handling_test.rb +0 -43
  110. data/test/fixtures/baidu_invalid_key +0 -1
  111. data/test/fixtures/baidu_no_results +0 -1
  112. data/test/fixtures/baidu_reverse +0 -1
  113. data/test/fixtures/baidu_shanghai_pearl_tower +0 -12
  114. data/test/fixtures/bing_invalid_key +0 -1
  115. data/test/fixtures/bing_madison_square_garden +0 -40
  116. data/test/fixtures/bing_no_results +0 -16
  117. data/test/fixtures/bing_reverse +0 -42
  118. data/test/fixtures/esri_madison_square_garden +0 -59
  119. data/test/fixtures/esri_no_results +0 -8
  120. data/test/fixtures/esri_reverse +0 -21
  121. data/test/fixtures/freegeoip_74_200_247_59 +0 -12
  122. data/test/fixtures/freegeoip_no_results +0 -1
  123. data/test/fixtures/geocoder_ca_madison_square_garden +0 -1
  124. data/test/fixtures/geocoder_ca_no_results +0 -1
  125. data/test/fixtures/geocoder_ca_reverse +0 -34
  126. data/test/fixtures/geocoder_us_madison_square_garden +0 -1
  127. data/test/fixtures/geocoder_us_no_results +0 -1
  128. data/test/fixtures/google_garbage +0 -456
  129. data/test/fixtures/google_madison_square_garden +0 -57
  130. data/test/fixtures/google_no_city_data +0 -44
  131. data/test/fixtures/google_no_locality +0 -51
  132. data/test/fixtures/google_no_results +0 -4
  133. data/test/fixtures/google_over_limit +0 -4
  134. data/test/fixtures/mapquest_error +0 -16
  135. data/test/fixtures/mapquest_invalid_api_key +0 -16
  136. data/test/fixtures/mapquest_invalid_request +0 -16
  137. data/test/fixtures/mapquest_madison_square_garden +0 -52
  138. data/test/fixtures/mapquest_no_results +0 -16
  139. data/test/fixtures/maxmind_24_24_24_21 +0 -1
  140. data/test/fixtures/maxmind_24_24_24_22 +0 -1
  141. data/test/fixtures/maxmind_24_24_24_23 +0 -1
  142. data/test/fixtures/maxmind_24_24_24_24 +0 -1
  143. data/test/fixtures/maxmind_74_200_247_59 +0 -1
  144. data/test/fixtures/maxmind_invalid_key +0 -1
  145. data/test/fixtures/maxmind_no_results +0 -1
  146. data/test/fixtures/nominatim_madison_square_garden +0 -150
  147. data/test/fixtures/nominatim_no_results +0 -1
  148. data/test/fixtures/ovi_madison_square_garden +0 -72
  149. data/test/fixtures/ovi_no_results +0 -8
  150. data/test/fixtures/yahoo_error +0 -1
  151. data/test/fixtures/yahoo_invalid_key +0 -2
  152. data/test/fixtures/yahoo_madison_square_garden +0 -52
  153. data/test/fixtures/yahoo_no_results +0 -10
  154. data/test/fixtures/yahoo_over_limit +0 -2
  155. data/test/fixtures/yandex_invalid_key +0 -1
  156. data/test/fixtures/yandex_kremlin +0 -48
  157. data/test/fixtures/yandex_no_city_and_town +0 -112
  158. data/test/fixtures/yandex_no_results +0 -16
  159. data/test/geocoder_test.rb +0 -59
  160. data/test/https_test.rb +0 -16
  161. data/test/integration/smoke_test.rb +0 -26
  162. data/test/lookup_test.rb +0 -117
  163. data/test/method_aliases_test.rb +0 -25
  164. data/test/mongoid_test.rb +0 -46
  165. data/test/mongoid_test_helper.rb +0 -43
  166. data/test/near_test.rb +0 -61
  167. data/test/oauth_util_test.rb +0 -30
  168. data/test/proxy_test.rb +0 -36
  169. data/test/query_test.rb +0 -52
  170. data/test/request_test.rb +0 -29
  171. data/test/result_test.rb +0 -42
  172. data/test/services_test.rb +0 -393
  173. data/test/test_helper.rb +0 -289
  174. data/test/test_mode_test.rb +0 -59
@@ -0,0 +1,49 @@
1
+ require 'geocoder/results/base'
2
+
3
+ module Geocoder::Result
4
+ class MaxmindLocal < Base
5
+
6
+ def address(format = :full)
7
+ s = state.to_s == "" ? "" : ", #{state}"
8
+ "#{city}#{s} #{postal_code}, #{country}".sub(/^[ ,]*/, "")
9
+ end
10
+
11
+ def coordinates
12
+ [@data[:latitude], @data[:longitude]]
13
+ end
14
+
15
+ def city
16
+ @data[:city_name]
17
+ end
18
+
19
+ def state
20
+ @data[:region_name]
21
+ end
22
+
23
+ def state_code
24
+ "" # Not available in Maxmind's database
25
+ end
26
+
27
+ def country
28
+ @data[:country_name]
29
+ end
30
+
31
+ def country_code
32
+ @data[:country_code2]
33
+ end
34
+
35
+ def postal_code
36
+ @data[:postal_code]
37
+ end
38
+
39
+ def self.response_attributes
40
+ %w[ip]
41
+ end
42
+
43
+ response_attributes.each do |a|
44
+ define_method a do
45
+ @data[a]
46
+ end
47
+ end
48
+ end
49
+ end
@@ -4,7 +4,7 @@ module Geocoder::Result
4
4
  class Nominatim < Base
5
5
 
6
6
  def poi
7
- %w[stadium bus_stop tram_stop].each do |key|
7
+ %w[building university school hospital mall hotel restaurant stadium bus_stop tram_stop].each do |key|
8
8
  return @data['address'][key] if @data['address'].key?(key)
9
9
  end
10
10
  return nil
@@ -78,6 +78,11 @@ module Geocoder::Result
78
78
  @data['type']
79
79
  end
80
80
 
81
+ def viewport
82
+ south, north, west, east = @data['boundingbox'].map(&:to_f)
83
+ [south, west, north, east]
84
+ end
85
+
81
86
  def self.response_attributes
82
87
  %w[place_id osm_type osm_id boundingbox license
83
88
  polygonpoints display_name class type stadium]
@@ -0,0 +1,106 @@
1
+ require 'geocoder/results/base'
2
+
3
+ module Geocoder::Result
4
+ class Okf < Base
5
+
6
+ def coordinates
7
+ ['lat', 'lng'].map{ |i| geometry['location'][i] }
8
+ end
9
+
10
+ def address(format = :full)
11
+ formatted_address
12
+ end
13
+
14
+ def city
15
+ fields = [:locality, :sublocality,
16
+ :administrative_area_level_3,
17
+ :administrative_area_level_2]
18
+ fields.each do |f|
19
+ if entity = address_components_of_type(f).first
20
+ return entity['long_name']
21
+ end
22
+ end
23
+ return nil # no appropriate components found
24
+ end
25
+
26
+ def state
27
+ ""
28
+ end
29
+
30
+ def sub_state
31
+ ""
32
+ end
33
+
34
+ def state_code
35
+ ""
36
+ end
37
+
38
+ def country
39
+ if country = address_components_of_type(:country).first
40
+ country['long_name']
41
+ end
42
+ end
43
+
44
+ def country_code
45
+ if country = address_components_of_type(:country).first
46
+ country['short_name']
47
+ end
48
+ end
49
+
50
+ def postal_code
51
+ if postal = address_components_of_type(:postal_code).first
52
+ postal['long_name']
53
+ end
54
+ end
55
+
56
+ def route
57
+ if route = address_components_of_type(:route).first
58
+ route['long_name']
59
+ end
60
+ end
61
+
62
+ def street_number
63
+ if street_number = address_components_of_type(:street_number).first
64
+ street_number['long_name']
65
+ end
66
+ end
67
+
68
+ def street_address
69
+ [route, street_number].compact.join(' ')
70
+ end
71
+
72
+ def types
73
+ @data['types']
74
+ end
75
+
76
+ def formatted_address
77
+ @data['formatted_address']
78
+ end
79
+
80
+ def address_components
81
+ @data['address_components']
82
+ end
83
+
84
+ ##
85
+ # Get address components of a given type. Valid types are defined in
86
+ # Google's Geocoding API documentation and include (among others):
87
+ #
88
+ # :street_number
89
+ # :locality
90
+ # :neighborhood
91
+ # :route
92
+ # :postal_code
93
+ #
94
+ def address_components_of_type(type)
95
+ address_components.select{ |c| c['types'].include?(type.to_s) }
96
+ end
97
+
98
+ def geometry
99
+ @data['geometry']
100
+ end
101
+
102
+ def precision
103
+ geometry['location_type'] if geometry
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,90 @@
1
+ require 'geocoder/results/base'
2
+
3
+ module Geocoder::Result
4
+ class Opencagedata < Base
5
+
6
+ def poi
7
+ %w[stadium bus_stop tram_stop].each do |key|
8
+ return @data['components'][key] if @data['components'].key?(key)
9
+ end
10
+ return nil
11
+ end
12
+
13
+ def house_number
14
+ @data['components']['house_number']
15
+ end
16
+
17
+ def address
18
+ @data['formatted']
19
+ end
20
+
21
+ def street
22
+ %w[road pedestrian highway].each do |key|
23
+ return @data['components'][key] if @data['components'].key?(key)
24
+ end
25
+ return nil
26
+ end
27
+
28
+ def city
29
+ %w[city town village hamlet].each do |key|
30
+ return @data['components'][key] if @data['components'].key?(key)
31
+ end
32
+ return nil
33
+ end
34
+
35
+ def village
36
+ @data['components']['village']
37
+ end
38
+
39
+
40
+ def state
41
+ @data['components']['state']
42
+ end
43
+
44
+ alias_method :state_code, :state
45
+
46
+ def postal_code
47
+ @data['components']['postcode'].to_s
48
+ end
49
+
50
+ def county
51
+ @data['components']['county']
52
+ end
53
+
54
+ def country
55
+ @data['components']['country']
56
+ end
57
+
58
+ def country_code
59
+ @data['components']['country_code']
60
+ end
61
+
62
+ def suburb
63
+ @data['components']['suburb']
64
+ end
65
+
66
+ def coordinates
67
+ [@data['geometry']['lat'].to_f, @data['geometry']['lng'].to_f]
68
+ end
69
+
70
+ def viewport
71
+ bounds = @data['bounds'] || fail
72
+ south, west = %w(lat lng).map { |i| bounds['southwest'][i] }
73
+ north, east = %w(lat lng).map { |i| bounds['northeast'][i] }
74
+ [south, west, north, east]
75
+ end
76
+
77
+ def self.response_attributes
78
+ %w[boundingbox license
79
+ formatted stadium]
80
+ end
81
+
82
+ response_attributes.each do |a|
83
+ unless method_defined?(a)
84
+ define_method a do
85
+ @data[a]
86
+ end
87
+ end
88
+ end
89
+ end
90
+ end
@@ -53,6 +53,15 @@ module Geocoder::Result
53
53
  address_data['Country']
54
54
  end
55
55
 
56
+ def viewport
57
+ map_view = data['Location']['MapView'] || fail
58
+ south = map_view['BottomRight']['Latitude']
59
+ west = map_view['TopLeft']['Longitude']
60
+ north = map_view['TopLeft']['Latitude']
61
+ east = map_view['BottomRight']['Longitude']
62
+ [south, west, north, east]
63
+ end
64
+
56
65
  private # ----------------------------------------------------------------
57
66
 
58
67
  def address_data
@@ -0,0 +1,58 @@
1
+ require 'geocoder/results/base'
2
+
3
+ module Geocoder::Result
4
+ class Pelias < Base
5
+ def address(format = :full)
6
+ properties['label']
7
+ end
8
+
9
+ def city
10
+ locality
11
+ end
12
+
13
+ def coordinates
14
+ geometry['coordinates'].reverse
15
+ end
16
+
17
+ def country_code
18
+ properties['country_a']
19
+ end
20
+
21
+ def postal_code
22
+ properties['postalcode'].to_s
23
+ end
24
+
25
+ def province
26
+ state
27
+ end
28
+
29
+ def state
30
+ properties['region']
31
+ end
32
+
33
+ def state_code
34
+ properties['region_a']
35
+ end
36
+
37
+ def self.response_attributes
38
+ %w[county confidence country gid id layer localadmin locality neighborhood]
39
+ end
40
+
41
+ response_attributes.each do |a|
42
+ define_method a do
43
+ properties[a]
44
+ end
45
+ end
46
+
47
+ private
48
+
49
+ def geometry
50
+ @data.fetch('geometry', {})
51
+ end
52
+
53
+ def properties
54
+ @data.fetch('properties', {})
55
+ end
56
+ end
57
+ end
58
+
@@ -0,0 +1,40 @@
1
+ require 'geocoder/results/base'
2
+
3
+ module Geocoder::Result
4
+ class Pointpin < Base
5
+
6
+ def address
7
+ [ city_name, state, postal_code, country ].select{ |i| i.to_s != "" }.join(", ")
8
+ end
9
+
10
+ def city
11
+ @data['city_name']
12
+ end
13
+
14
+ def state
15
+ @data['region_name']
16
+ end
17
+
18
+ def state_code
19
+ @data['region_code']
20
+ end
21
+
22
+ def country
23
+ @data['country_name']
24
+ end
25
+
26
+ def postal_code
27
+ @data['postcode']
28
+ end
29
+
30
+ def self.response_attributes
31
+ %w[continent_code ip country_code country_name region_name city_name postcode latitude longitude time_zone languages]
32
+ end
33
+
34
+ response_attributes.each do |a|
35
+ define_method a do
36
+ @data[a]
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,42 @@
1
+ require 'geocoder/results/base'
2
+
3
+ module Geocoder::Result
4
+ class PostcodeAnywhereUk < Base
5
+
6
+ def coordinates
7
+ [@data['Latitude'].to_f, @data['Longitude'].to_f]
8
+ end
9
+
10
+ def blank_result
11
+ ''
12
+ end
13
+ alias_method :state, :blank_result
14
+ alias_method :state_code, :blank_result
15
+ alias_method :postal_code, :blank_result
16
+
17
+ def address
18
+ @data['Location']
19
+ end
20
+
21
+ def city
22
+ # is this too big a jump to assume that the API always
23
+ # returns a City, County as the last elements?
24
+ city = @data['Location'].split(',')[-2] || blank_result
25
+ city.strip
26
+ end
27
+
28
+ def os_grid
29
+ @data['OsGrid']
30
+ end
31
+
32
+ # This is a UK only API; all results are UK specific and
33
+ # so ommitted from API response.
34
+ def country
35
+ 'United Kingdom'
36
+ end
37
+
38
+ def country_code
39
+ 'UK'
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,106 @@
1
+ require 'geocoder/lookups/base'
2
+
3
+ module Geocoder::Result
4
+ class SmartyStreets < Base
5
+ def coordinates
6
+ %w(latitude longitude).map do |i|
7
+ zipcode_endpoint? ? zipcodes.first[i] : metadata[i]
8
+ end
9
+ end
10
+
11
+ def address
12
+ [
13
+ delivery_line_1,
14
+ delivery_line_2,
15
+ last_line
16
+ ].select{ |i| i.to_s != "" }.join(" ")
17
+ end
18
+
19
+ def state
20
+ zipcode_endpoint? ?
21
+ city_states.first['state'] :
22
+ components['state_abbreviation']
23
+ end
24
+
25
+ def state_code
26
+ zipcode_endpoint? ?
27
+ city_states.first['state_abbreviation'] :
28
+ components['state_abbreviation']
29
+ end
30
+
31
+ def country
32
+ # SmartyStreets returns results for USA only
33
+ "United States"
34
+ end
35
+
36
+ def country_code
37
+ # SmartyStreets returns results for USA only
38
+ "US"
39
+ end
40
+
41
+ ## Extra methods not in base.rb ------------------------
42
+
43
+ def street
44
+ components['street_name']
45
+ end
46
+
47
+ def city
48
+ zipcode_endpoint? ?
49
+ city_states.first['city'] :
50
+ components['city_name']
51
+ end
52
+
53
+ def zipcode
54
+ zipcode_endpoint? ?
55
+ zipcodes.first['zipcode'] :
56
+ components['zipcode']
57
+ end
58
+ alias_method :postal_code, :zipcode
59
+
60
+ def zip4
61
+ components['plus4_code']
62
+ end
63
+ alias_method :postal_code_extended, :zip4
64
+
65
+ def fips
66
+ zipcode_endpoint? ?
67
+ zipcodes.first['county_fips'] :
68
+ metadata['county_fips']
69
+ end
70
+
71
+ def zipcode_endpoint?
72
+ zipcodes.any?
73
+ end
74
+
75
+ [
76
+ :delivery_line_1,
77
+ :delivery_line_2,
78
+ :last_line,
79
+ :delivery_point_barcode,
80
+ :addressee
81
+ ].each do |m|
82
+ define_method(m) do
83
+ @data[m.to_s] || ''
84
+ end
85
+ end
86
+
87
+ [
88
+ :components,
89
+ :metadata,
90
+ :analysis
91
+ ].each do |m|
92
+ define_method(m) do
93
+ @data[m.to_s] || {}
94
+ end
95
+ end
96
+
97
+ [
98
+ :city_states,
99
+ :zipcodes
100
+ ].each do |m|
101
+ define_method(m) do
102
+ @data[m.to_s] || []
103
+ end
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,45 @@
1
+ require 'geocoder/results/base'
2
+
3
+ module Geocoder::Result
4
+ class Telize < Base
5
+
6
+ def address(format = :full)
7
+ s = state_code.to_s == "" ? "" : ", #{state_code}"
8
+ "#{city}#{s} #{postal_code}, #{country}".sub(/^[ ,]*/, "")
9
+ end
10
+
11
+ def city
12
+ @data['city']
13
+ end
14
+
15
+ def state
16
+ @data['region']
17
+ end
18
+
19
+ def state_code
20
+ @data['region_code']
21
+ end
22
+
23
+ def country
24
+ @data['country']
25
+ end
26
+
27
+ def country_code
28
+ @data['country_code']
29
+ end
30
+
31
+ def postal_code
32
+ @data['postal_code']
33
+ end
34
+
35
+ def self.response_attributes
36
+ %w[timezone isp dma_code area_code ip asn continent_code country_code3]
37
+ end
38
+
39
+ response_attributes.each do |a|
40
+ define_method a do
41
+ @data[a]
42
+ end
43
+ end
44
+ end
45
+ end
@@ -4,13 +4,30 @@ module Geocoder
4
4
  module Result
5
5
  class Test < Base
6
6
 
7
- %w[latitude longitude city state state_code province
8
- province_code postal_code country country_code address
9
- street_address street_number route].each do |attr|
7
+ def self.add_result_attribute(attr)
8
+ begin
9
+ remove_method(attr) if method_defined?(attr)
10
+ rescue NameError # method defined on superclass
11
+ end
12
+
10
13
  define_method(attr) do
11
14
  @data[attr.to_s] || @data[attr.to_sym]
12
15
  end
13
16
  end
17
+
18
+ %w[latitude longitude neighborhood city state state_code sub_state
19
+ sub_state_code province province_code postal_code country
20
+ country_code address street_address street_number route geometry].each do |attr|
21
+ add_result_attribute(attr)
22
+ end
23
+
24
+ def initialize(data)
25
+ data.each_key do |attr|
26
+ Test.add_result_attribute(attr)
27
+ end
28
+
29
+ super
30
+ end
14
31
  end
15
32
  end
16
33
  end
@@ -12,9 +12,10 @@ module Geocoder::Result
12
12
  end
13
13
 
14
14
  def city
15
- if state.empty? and address_details.has_key? 'Locality'
15
+ if state.empty? and address_details and address_details.has_key? 'Locality'
16
16
  address_details['Locality']['LocalityName']
17
- elsif sub_state.empty?
17
+ elsif sub_state.empty? and address_details and address_details.has_key? 'AdministrativeArea' and
18
+ address_details['AdministrativeArea'].has_key? 'Locality'
18
19
  address_details['AdministrativeArea']['Locality']['LocalityName']
19
20
  elsif not sub_state_city.empty?
20
21
  sub_state_city
@@ -32,7 +33,7 @@ module Geocoder::Result
32
33
  end
33
34
 
34
35
  def state
35
- if address_details['AdministrativeArea']
36
+ if address_details and address_details['AdministrativeArea']
36
37
  address_details['AdministrativeArea']['AdministrativeAreaName']
37
38
  else
38
39
  ""
@@ -40,7 +41,7 @@ module Geocoder::Result
40
41
  end
41
42
 
42
43
  def sub_state
43
- if !state.empty? and address_details['AdministrativeArea']['SubAdministrativeArea']
44
+ if !state.empty? and address_details and address_details['AdministrativeArea']['SubAdministrativeArea']
44
45
  address_details['AdministrativeArea']['SubAdministrativeArea']['SubAdministrativeAreaName']
45
46
  else
46
47
  ""
@@ -59,10 +60,21 @@ module Geocoder::Result
59
60
  address_details['Locality']['Premise']['PremiseName']
60
61
  end
61
62
 
63
+ def kind
64
+ @data['GeoObject']['metaDataProperty']['GeocoderMetaData']['kind']
65
+ end
66
+
62
67
  def precision
63
68
  @data['GeoObject']['metaDataProperty']['GeocoderMetaData']['precision']
64
69
  end
65
70
 
71
+ def viewport
72
+ envelope = @data['GeoObject']['boundedBy']['Envelope'] || fail
73
+ east, north = envelope['upperCorner'].split(' ').map(&:to_f)
74
+ west, south = envelope['lowerCorner'].split(' ').map(&:to_f)
75
+ [south, west, north, east]
76
+ end
77
+
66
78
  private # ----------------------------------------------------------------
67
79
 
68
80
  def address_details
@@ -70,8 +82,8 @@ module Geocoder::Result
70
82
  end
71
83
 
72
84
  def sub_state_city
73
- if sub_state && sub_state["Locality"]
74
- sub_state['Locality']['LocalityName']
85
+ if !sub_state.empty? and address_details and address_details['AdministrativeArea']['SubAdministrativeArea'].has_key? 'Locality'
86
+ address_details['AdministrativeArea']['SubAdministrativeArea']['Locality']['LocalityName'] || ""
75
87
  else
76
88
  ""
77
89
  end