bw-geocoder 1.2.5

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 (233) hide show
  1. data/.gitignore +6 -0
  2. data/.travis.yml +31 -0
  3. data/CHANGELOG.md +377 -0
  4. data/LICENSE +20 -0
  5. data/README.md +1041 -0
  6. data/Rakefile +25 -0
  7. data/bin/geocode +5 -0
  8. data/examples/autoexpire_cache_dalli.rb +62 -0
  9. data/examples/autoexpire_cache_redis.rb +28 -0
  10. data/examples/cache_bypass.rb +48 -0
  11. data/gemfiles/Gemfile.mongoid-2.4.x +16 -0
  12. data/lib/generators/geocoder/config/config_generator.rb +14 -0
  13. data/lib/generators/geocoder/config/templates/initializer.rb +21 -0
  14. data/lib/generators/geocoder/maxmind/geolite_city_generator.rb +28 -0
  15. data/lib/generators/geocoder/maxmind/geolite_country_generator.rb +28 -0
  16. data/lib/generators/geocoder/maxmind/templates/migration/geolite_city.rb +30 -0
  17. data/lib/generators/geocoder/maxmind/templates/migration/geolite_country.rb +17 -0
  18. data/lib/geocoder/cache.rb +90 -0
  19. data/lib/geocoder/calculations.rb +428 -0
  20. data/lib/geocoder/cli.rb +121 -0
  21. data/lib/geocoder/configuration.rb +124 -0
  22. data/lib/geocoder/configuration_hash.rb +11 -0
  23. data/lib/geocoder/exceptions.rb +21 -0
  24. data/lib/geocoder/ip_address.rb +21 -0
  25. data/lib/geocoder/lookup.rb +100 -0
  26. data/lib/geocoder/lookups/baidu.rb +55 -0
  27. data/lib/geocoder/lookups/baidu_ip.rb +54 -0
  28. data/lib/geocoder/lookups/base.rb +302 -0
  29. data/lib/geocoder/lookups/bing.rb +59 -0
  30. data/lib/geocoder/lookups/dstk.rb +20 -0
  31. data/lib/geocoder/lookups/esri.rb +48 -0
  32. data/lib/geocoder/lookups/freegeoip.rb +47 -0
  33. data/lib/geocoder/lookups/geocoder_ca.rb +54 -0
  34. data/lib/geocoder/lookups/geocoder_us.rb +39 -0
  35. data/lib/geocoder/lookups/geocodio.rb +42 -0
  36. data/lib/geocoder/lookups/google.rb +67 -0
  37. data/lib/geocoder/lookups/google_places_details.rb +50 -0
  38. data/lib/geocoder/lookups/google_premier.rb +47 -0
  39. data/lib/geocoder/lookups/here.rb +62 -0
  40. data/lib/geocoder/lookups/ip_address_labs.rb +43 -0
  41. data/lib/geocoder/lookups/mapquest.rb +60 -0
  42. data/lib/geocoder/lookups/maxmind.rb +90 -0
  43. data/lib/geocoder/lookups/maxmind_local.rb +58 -0
  44. data/lib/geocoder/lookups/nominatim.rb +52 -0
  45. data/lib/geocoder/lookups/okf.rb +43 -0
  46. data/lib/geocoder/lookups/opencagedata.rb +58 -0
  47. data/lib/geocoder/lookups/ovi.rb +62 -0
  48. data/lib/geocoder/lookups/pointpin.rb +68 -0
  49. data/lib/geocoder/lookups/smarty_streets.rb +45 -0
  50. data/lib/geocoder/lookups/telize.rb +40 -0
  51. data/lib/geocoder/lookups/test.rb +44 -0
  52. data/lib/geocoder/lookups/yahoo.rb +88 -0
  53. data/lib/geocoder/lookups/yandex.rb +54 -0
  54. data/lib/geocoder/models/active_record.rb +50 -0
  55. data/lib/geocoder/models/base.rb +39 -0
  56. data/lib/geocoder/models/mongo_base.rb +64 -0
  57. data/lib/geocoder/models/mongo_mapper.rb +26 -0
  58. data/lib/geocoder/models/mongoid.rb +32 -0
  59. data/lib/geocoder/query.rb +111 -0
  60. data/lib/geocoder/railtie.rb +26 -0
  61. data/lib/geocoder/request.rb +25 -0
  62. data/lib/geocoder/results/baidu.rb +79 -0
  63. data/lib/geocoder/results/baidu_ip.rb +62 -0
  64. data/lib/geocoder/results/base.rb +67 -0
  65. data/lib/geocoder/results/bing.rb +48 -0
  66. data/lib/geocoder/results/dstk.rb +6 -0
  67. data/lib/geocoder/results/esri.rb +51 -0
  68. data/lib/geocoder/results/freegeoip.rb +45 -0
  69. data/lib/geocoder/results/geocoder_ca.rb +60 -0
  70. data/lib/geocoder/results/geocoder_us.rb +39 -0
  71. data/lib/geocoder/results/geocodio.rb +66 -0
  72. data/lib/geocoder/results/google.rb +124 -0
  73. data/lib/geocoder/results/google_places_details.rb +35 -0
  74. data/lib/geocoder/results/google_premier.rb +6 -0
  75. data/lib/geocoder/results/here.rb +62 -0
  76. data/lib/geocoder/results/ip_address_labs.rb +78 -0
  77. data/lib/geocoder/results/mapquest.rb +51 -0
  78. data/lib/geocoder/results/maxmind.rb +135 -0
  79. data/lib/geocoder/results/maxmind_local.rb +49 -0
  80. data/lib/geocoder/results/nominatim.rb +94 -0
  81. data/lib/geocoder/results/okf.rb +106 -0
  82. data/lib/geocoder/results/opencagedata.rb +82 -0
  83. data/lib/geocoder/results/ovi.rb +62 -0
  84. data/lib/geocoder/results/pointpin.rb +44 -0
  85. data/lib/geocoder/results/smarty_streets.rb +106 -0
  86. data/lib/geocoder/results/telize.rb +45 -0
  87. data/lib/geocoder/results/test.rb +33 -0
  88. data/lib/geocoder/results/yahoo.rb +55 -0
  89. data/lib/geocoder/results/yandex.rb +84 -0
  90. data/lib/geocoder/sql.rb +107 -0
  91. data/lib/geocoder/stores/active_record.rb +278 -0
  92. data/lib/geocoder/stores/base.rb +127 -0
  93. data/lib/geocoder/stores/mongo_base.rb +89 -0
  94. data/lib/geocoder/stores/mongo_mapper.rb +13 -0
  95. data/lib/geocoder/stores/mongoid.rb +13 -0
  96. data/lib/geocoder/version.rb +3 -0
  97. data/lib/geocoder.rb +47 -0
  98. data/lib/hash_recursive_merge.rb +74 -0
  99. data/lib/maxmind_database.rb +109 -0
  100. data/lib/oauth_util.rb +112 -0
  101. data/lib/tasks/geocoder.rake +29 -0
  102. data/lib/tasks/maxmind.rake +73 -0
  103. data/test/fixtures/baidu_invalid_key +1 -0
  104. data/test/fixtures/baidu_ip_202_198_16_3 +19 -0
  105. data/test/fixtures/baidu_ip_invalid_key +1 -0
  106. data/test/fixtures/baidu_ip_no_results +1 -0
  107. data/test/fixtures/baidu_no_results +1 -0
  108. data/test/fixtures/baidu_reverse +1 -0
  109. data/test/fixtures/baidu_shanghai_pearl_tower +12 -0
  110. data/test/fixtures/bing_invalid_key +1 -0
  111. data/test/fixtures/bing_madison_square_garden +40 -0
  112. data/test/fixtures/bing_no_results +16 -0
  113. data/test/fixtures/bing_reverse +42 -0
  114. data/test/fixtures/cloudmade_invalid_key +1 -0
  115. data/test/fixtures/cloudmade_madison_square_garden +1 -0
  116. data/test/fixtures/cloudmade_no_results +1 -0
  117. data/test/fixtures/esri_madison_square_garden +59 -0
  118. data/test/fixtures/esri_no_results +8 -0
  119. data/test/fixtures/esri_reverse +21 -0
  120. data/test/fixtures/freegeoip_74_200_247_59 +12 -0
  121. data/test/fixtures/freegeoip_no_results +1 -0
  122. data/test/fixtures/geocoder_ca_madison_square_garden +1 -0
  123. data/test/fixtures/geocoder_ca_no_results +1 -0
  124. data/test/fixtures/geocoder_ca_reverse +34 -0
  125. data/test/fixtures/geocoder_us_madison_square_garden +1 -0
  126. data/test/fixtures/geocoder_us_no_results +1 -0
  127. data/test/fixtures/geocodio_1101_pennsylvania_ave +1 -0
  128. data/test/fixtures/geocodio_bad_api_key +3 -0
  129. data/test/fixtures/geocodio_invalid +4 -0
  130. data/test/fixtures/geocodio_no_results +1 -0
  131. data/test/fixtures/geocodio_over_query_limit +4 -0
  132. data/test/fixtures/google_garbage +456 -0
  133. data/test/fixtures/google_madison_square_garden +57 -0
  134. data/test/fixtures/google_no_city_data +44 -0
  135. data/test/fixtures/google_no_locality +51 -0
  136. data/test/fixtures/google_no_results +4 -0
  137. data/test/fixtures/google_over_limit +4 -0
  138. data/test/fixtures/google_places_details_invalid_request +4 -0
  139. data/test/fixtures/google_places_details_madison_square_garden +120 -0
  140. data/test/fixtures/google_places_details_no_results +4 -0
  141. data/test/fixtures/google_places_details_no_reviews +60 -0
  142. data/test/fixtures/google_places_details_no_types +66 -0
  143. data/test/fixtures/here_madison_square_garden +72 -0
  144. data/test/fixtures/here_no_results +8 -0
  145. data/test/fixtures/mapquest_error +16 -0
  146. data/test/fixtures/mapquest_invalid_api_key +16 -0
  147. data/test/fixtures/mapquest_invalid_request +16 -0
  148. data/test/fixtures/mapquest_madison_square_garden +52 -0
  149. data/test/fixtures/mapquest_no_results +16 -0
  150. data/test/fixtures/maxmind_24_24_24_21 +1 -0
  151. data/test/fixtures/maxmind_24_24_24_22 +1 -0
  152. data/test/fixtures/maxmind_24_24_24_23 +1 -0
  153. data/test/fixtures/maxmind_24_24_24_24 +1 -0
  154. data/test/fixtures/maxmind_74_200_247_59 +1 -0
  155. data/test/fixtures/maxmind_invalid_key +1 -0
  156. data/test/fixtures/maxmind_no_results +1 -0
  157. data/test/fixtures/nominatim_madison_square_garden +150 -0
  158. data/test/fixtures/nominatim_no_results +1 -0
  159. data/test/fixtures/nominatim_over_limit +1 -0
  160. data/test/fixtures/okf_kirstinmaki +67 -0
  161. data/test/fixtures/okf_no_results +4 -0
  162. data/test/fixtures/opencagedata_invalid_api_key +25 -0
  163. data/test/fixtures/opencagedata_invalid_request +26 -0
  164. data/test/fixtures/opencagedata_madison_square_garden +73 -0
  165. data/test/fixtures/opencagedata_no_results +29 -0
  166. data/test/fixtures/opencagedata_over_limit +31 -0
  167. data/test/fixtures/ovi_madison_square_garden +72 -0
  168. data/test/fixtures/ovi_no_results +8 -0
  169. data/test/fixtures/pointpin_10_10_10_10 +1 -0
  170. data/test/fixtures/pointpin_555_555_555_555 +1 -0
  171. data/test/fixtures/pointpin_80_111_555_555 +1 -0
  172. data/test/fixtures/pointpin_no_results +1 -0
  173. data/test/fixtures/smarty_streets_11211 +1 -0
  174. data/test/fixtures/smarty_streets_madison_square_garden +47 -0
  175. data/test/fixtures/smarty_streets_no_results +1 -0
  176. data/test/fixtures/telize_10_10_10_10 +1 -0
  177. data/test/fixtures/telize_555_555_555_555 +4 -0
  178. data/test/fixtures/telize_74_200_247_59 +1 -0
  179. data/test/fixtures/telize_no_results +1 -0
  180. data/test/fixtures/yahoo_error +1 -0
  181. data/test/fixtures/yahoo_invalid_key +2 -0
  182. data/test/fixtures/yahoo_madison_square_garden +52 -0
  183. data/test/fixtures/yahoo_no_results +10 -0
  184. data/test/fixtures/yahoo_over_limit +2 -0
  185. data/test/fixtures/yandex_canada_rue_dupuis_14 +446 -0
  186. data/test/fixtures/yandex_invalid_key +1 -0
  187. data/test/fixtures/yandex_kremlin +48 -0
  188. data/test/fixtures/yandex_new_york +1 -0
  189. data/test/fixtures/yandex_no_city_and_town +112 -0
  190. data/test/fixtures/yandex_no_results +16 -0
  191. data/test/integration/http_client_test.rb +31 -0
  192. data/test/mongoid_test_helper.rb +43 -0
  193. data/test/test_helper.rb +386 -0
  194. data/test/unit/active_record_test.rb +16 -0
  195. data/test/unit/cache_test.rb +37 -0
  196. data/test/unit/calculations_test.rb +220 -0
  197. data/test/unit/configuration_test.rb +55 -0
  198. data/test/unit/error_handling_test.rb +56 -0
  199. data/test/unit/geocoder_test.rb +78 -0
  200. data/test/unit/https_test.rb +17 -0
  201. data/test/unit/ip_address_test.rb +27 -0
  202. data/test/unit/lookup_test.rb +153 -0
  203. data/test/unit/lookups/bing_test.rb +68 -0
  204. data/test/unit/lookups/dstk_test.rb +26 -0
  205. data/test/unit/lookups/esri_test.rb +48 -0
  206. data/test/unit/lookups/freegeoip_test.rb +27 -0
  207. data/test/unit/lookups/geocoder_ca_test.rb +17 -0
  208. data/test/unit/lookups/geocodio_test.rb +55 -0
  209. data/test/unit/lookups/google_places_details_test.rb +122 -0
  210. data/test/unit/lookups/google_premier_test.rb +22 -0
  211. data/test/unit/lookups/google_test.rb +84 -0
  212. data/test/unit/lookups/mapquest_test.rb +60 -0
  213. data/test/unit/lookups/maxmind_local_test.rb +28 -0
  214. data/test/unit/lookups/maxmind_test.rb +63 -0
  215. data/test/unit/lookups/nominatim_test.rb +31 -0
  216. data/test/unit/lookups/okf_test.rb +38 -0
  217. data/test/unit/lookups/opencagedata_test.rb +64 -0
  218. data/test/unit/lookups/pointpin_test.rb +30 -0
  219. data/test/unit/lookups/smarty_streets_test.rb +71 -0
  220. data/test/unit/lookups/telize_test.rb +36 -0
  221. data/test/unit/lookups/yahoo_test.rb +35 -0
  222. data/test/unit/method_aliases_test.rb +26 -0
  223. data/test/unit/model_test.rb +38 -0
  224. data/test/unit/mongoid_test.rb +47 -0
  225. data/test/unit/near_test.rb +87 -0
  226. data/test/unit/oauth_util_test.rb +31 -0
  227. data/test/unit/proxy_test.rb +37 -0
  228. data/test/unit/query_test.rb +52 -0
  229. data/test/unit/rake_task_test.rb +21 -0
  230. data/test/unit/request_test.rb +35 -0
  231. data/test/unit/result_test.rb +72 -0
  232. data/test/unit/test_mode_test.rb +70 -0
  233. metadata +281 -0
@@ -0,0 +1,32 @@
1
+ require 'geocoder/models/base'
2
+ require 'geocoder/models/mongo_base'
3
+
4
+ module Geocoder
5
+ module Model
6
+ module Mongoid
7
+ include Base
8
+ include MongoBase
9
+
10
+ def self.included(base); base.extend(self); end
11
+
12
+ private # --------------------------------------------------------------
13
+
14
+ def geocoder_file_name; "mongoid"; end
15
+ def geocoder_module_name; "Mongoid"; end
16
+
17
+ def geocoder_init(options)
18
+ super(options)
19
+ if options[:skip_index] == false
20
+ # create 2d index
21
+ if defined?(::Mongoid::VERSION) && ::Mongoid::VERSION >= "3"
22
+ index({ geocoder_options[:coordinates].to_sym => '2d' },
23
+ {:min => -180, :max => 180})
24
+ else
25
+ index [[ geocoder_options[:coordinates], '2d' ]],
26
+ :min => -180, :max => 180
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,111 @@
1
+ module Geocoder
2
+ class Query
3
+ attr_accessor :text, :options
4
+
5
+ def initialize(text, options = {})
6
+ self.text = text
7
+ self.options = options
8
+ end
9
+
10
+ def execute
11
+ lookup.search(text, options)
12
+ end
13
+
14
+ def to_s
15
+ text
16
+ end
17
+
18
+ def sanitized_text
19
+ if coordinates?
20
+ if text.is_a?(Array)
21
+ text.join(',')
22
+ else
23
+ text.split(/\s*,\s*/).join(',')
24
+ end
25
+ else
26
+ text
27
+ end
28
+ end
29
+
30
+ ##
31
+ # Get a Lookup object (which communicates with the remote geocoding API)
32
+ # appropriate to the Query text.
33
+ #
34
+ def lookup
35
+ if ip_address?
36
+ name = options[:ip_lookup] || Configuration.ip_lookup || Geocoder::Lookup.ip_services.first
37
+ else
38
+ name = options[:lookup] || Configuration.lookup || Geocoder::Lookup.street_services.first
39
+ end
40
+ Lookup.get(name)
41
+ end
42
+
43
+ def url
44
+ lookup.query_url(self)
45
+ end
46
+
47
+ ##
48
+ # Is the Query blank? (ie, should we not bother searching?)
49
+ # A query is considered blank if its text is nil or empty string AND
50
+ # no URL parameters are specified.
51
+ #
52
+ def blank?
53
+ !params_given? and (
54
+ (text.is_a?(Array) and text.compact.size < 2) or
55
+ text.to_s.match(/\A\s*\z/)
56
+ )
57
+ end
58
+
59
+ ##
60
+ # Does the Query text look like an IP address?
61
+ #
62
+ # Does not check for actual validity, just the appearance of four
63
+ # dot-delimited numbers.
64
+ #
65
+ def ip_address?
66
+ IpAddress.new(text).valid? rescue false
67
+ end
68
+
69
+ ##
70
+ # Is the Query text a loopback IP address?
71
+ #
72
+ def loopback_ip_address?
73
+ ip_address? && IpAddress.new(text).loopback?
74
+ end
75
+
76
+ ##
77
+ # Does the given string look like latitude/longitude coordinates?
78
+ #
79
+ def coordinates?
80
+ text.is_a?(Array) or (
81
+ text.is_a?(String) and
82
+ !!text.to_s.match(/\A-?[0-9\.]+, *-?[0-9\.]+\z/)
83
+ )
84
+ end
85
+
86
+ ##
87
+ # Return the latitude/longitude coordinates specified in the query,
88
+ # or nil if none.
89
+ #
90
+ def coordinates
91
+ sanitized_text.split(',') if coordinates?
92
+ end
93
+
94
+ ##
95
+ # Should reverse geocoding be performed for this query?
96
+ #
97
+ def reverse_geocode?
98
+ coordinates?
99
+ end
100
+
101
+ def language
102
+ options[:language]
103
+ end
104
+
105
+ private # ----------------------------------------------------------------
106
+
107
+ def params_given?
108
+ !!(options[:params].is_a?(Hash) and options[:params].keys.size > 0)
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,26 @@
1
+ require 'geocoder/models/active_record'
2
+
3
+ module Geocoder
4
+ if defined? Rails::Railtie
5
+ require 'rails'
6
+ class Railtie < Rails::Railtie
7
+ initializer 'geocoder.insert_into_active_record' do
8
+ ActiveSupport.on_load :active_record do
9
+ Geocoder::Railtie.insert
10
+ end
11
+ end
12
+ rake_tasks do
13
+ load "tasks/geocoder.rake"
14
+ load "tasks/maxmind.rake"
15
+ end
16
+ end
17
+ end
18
+
19
+ class Railtie
20
+ def self.insert
21
+ if defined?(::ActiveRecord)
22
+ ::ActiveRecord::Base.extend(Model::ActiveRecord)
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,25 @@
1
+ module Geocoder
2
+ module Request
3
+
4
+ def location
5
+ @location ||= begin
6
+ detected_ip = env['HTTP_X_REAL_IP'] || (
7
+ env['HTTP_X_FORWARDED_FOR'] &&
8
+ env['HTTP_X_FORWARDED_FOR'].split(",").first.strip
9
+ )
10
+ detected_ip = IpAddress.new(detected_ip.to_s)
11
+ if detected_ip.valid? and !detected_ip.loopback?
12
+ real_ip = detected_ip.to_s
13
+ else
14
+ real_ip = self.ip
15
+ end
16
+ Geocoder.search(real_ip).first
17
+ end
18
+ @location
19
+ end
20
+ end
21
+ end
22
+
23
+ if defined?(Rack) and defined?(Rack::Request)
24
+ Rack::Request.send :include, Geocoder::Request
25
+ end
@@ -0,0 +1,79 @@
1
+ require 'geocoder/results/base'
2
+
3
+ module Geocoder::Result
4
+ class Baidu < Base
5
+
6
+ def coordinates
7
+ ['lat', 'lng'].map{ |i| @data['location'][i] }
8
+ end
9
+
10
+ def address
11
+ @data['formatted_address']
12
+ end
13
+
14
+ def state
15
+ province
16
+ end
17
+
18
+ def province
19
+ @data['addressComponent']['province']
20
+ end
21
+
22
+ def city
23
+ @data['addressComponent']['city']
24
+ end
25
+
26
+ def district
27
+ @data['addressComponent']['district']
28
+ end
29
+
30
+ def street
31
+ @data['addressComponent']['street']
32
+ end
33
+
34
+ def street_number
35
+ @data['addressComponent']['street_number']
36
+ end
37
+
38
+ def formatted_address
39
+ @data['formatted_address']
40
+ end
41
+
42
+ def address_components
43
+ @data['addressComponent']
44
+ end
45
+
46
+ def state_code
47
+ ""
48
+ end
49
+
50
+ def postal_code
51
+ ""
52
+ end
53
+
54
+ def country
55
+ "China"
56
+ end
57
+
58
+ def country_code
59
+ "CN"
60
+ end
61
+
62
+ ##
63
+ # Get address components of a given type. Valid types are defined in
64
+ # Baidu's Geocoding API documentation and include (among others):
65
+ #
66
+ # :business
67
+ # :cityCode
68
+ #
69
+ def self.response_attributes
70
+ %w[business cityCode]
71
+ end
72
+
73
+ response_attributes.each do |a|
74
+ define_method a do
75
+ @data[a]
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,62 @@
1
+ require 'geocoder/results/base'
2
+
3
+ module Geocoder::Result
4
+ class BaiduIp < Base
5
+ def coordinates
6
+ [point['y'].to_f, point['x'].to_f]
7
+ end
8
+
9
+ def address
10
+ @data['address']
11
+ end
12
+
13
+ def state
14
+ province
15
+ end
16
+
17
+ def province
18
+ address_detail['province']
19
+ end
20
+
21
+ def city
22
+ address_detail['city']
23
+ end
24
+
25
+ def district
26
+ address_detail['district']
27
+ end
28
+
29
+ def street
30
+ address_detail['street']
31
+ end
32
+
33
+ def street_number
34
+ address_detail['street_number']
35
+ end
36
+
37
+ def state_code
38
+ ""
39
+ end
40
+
41
+ def postal_code
42
+ ""
43
+ end
44
+
45
+ def country
46
+ "China"
47
+ end
48
+
49
+ def country_code
50
+ "CN"
51
+ end
52
+
53
+ private
54
+ def address_detail
55
+ @data['address_detail']
56
+ end
57
+
58
+ def point
59
+ @data['point']
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,67 @@
1
+ module Geocoder
2
+ module Result
3
+ class Base
4
+
5
+ # data (hash) fetched from geocoding service
6
+ attr_accessor :data
7
+
8
+ # true if result came from cache, false if from request to geocoding
9
+ # service; nil if cache is not configured
10
+ attr_accessor :cache_hit
11
+
12
+ ##
13
+ # Takes a hash of data from a parsed geocoding service response.
14
+ #
15
+ def initialize(data)
16
+ @data = data
17
+ @cache_hit = nil
18
+ end
19
+
20
+ ##
21
+ # A string in the given format.
22
+ #
23
+ def address(format = :full)
24
+ fail
25
+ end
26
+
27
+ ##
28
+ # A two-element array: [lat, lon].
29
+ #
30
+ def coordinates
31
+ [@data['latitude'].to_f, @data['longitude'].to_f]
32
+ end
33
+
34
+ def latitude
35
+ coordinates[0]
36
+ end
37
+
38
+ def longitude
39
+ coordinates[1]
40
+ end
41
+
42
+ def state
43
+ fail
44
+ end
45
+
46
+ def province
47
+ state
48
+ end
49
+
50
+ def state_code
51
+ fail
52
+ end
53
+
54
+ def province_code
55
+ state_code
56
+ end
57
+
58
+ def country
59
+ fail
60
+ end
61
+
62
+ def country_code
63
+ fail
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,48 @@
1
+ require 'geocoder/results/base'
2
+
3
+ module Geocoder::Result
4
+ class Bing < Base
5
+
6
+ def address(format = :full)
7
+ @data['address']['formattedAddress']
8
+ end
9
+
10
+ def city
11
+ @data['address']['locality']
12
+ end
13
+
14
+ def state_code
15
+ @data['address']['adminDistrict']
16
+ end
17
+
18
+ alias_method :state, :state_code
19
+
20
+ def country
21
+ @data['address']['countryRegion']
22
+ end
23
+
24
+ alias_method :country_code, :country
25
+
26
+ def postal_code
27
+ @data['address']['postalCode']
28
+ end
29
+
30
+ def coordinates
31
+ @data['point']['coordinates']
32
+ end
33
+
34
+ def address_data
35
+ @data['address']
36
+ end
37
+
38
+ def self.response_attributes
39
+ %w[bbox name confidence entityType]
40
+ end
41
+
42
+ response_attributes.each do |a|
43
+ define_method a do
44
+ @data[a]
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,6 @@
1
+ require 'geocoder/results/google'
2
+
3
+ module Geocoder::Result
4
+ class Dstk < Google
5
+ end
6
+ end
@@ -0,0 +1,51 @@
1
+ require 'geocoder/results/base'
2
+
3
+ module Geocoder::Result
4
+ class Esri < Base
5
+
6
+ def address
7
+ address = reverse_geocode? ? 'Address' : 'Match_addr'
8
+ attributes[address]
9
+ end
10
+
11
+ def city
12
+ attributes['City']
13
+ end
14
+
15
+ def state_code
16
+ attributes['Region']
17
+ end
18
+
19
+ alias_method :state, :state_code
20
+
21
+ def country
22
+ country = reverse_geocode? ? "CountryCode" : "Country"
23
+ attributes[country]
24
+ end
25
+
26
+ alias_method :country_code, :country
27
+
28
+ def postal_code
29
+ attributes['Postal']
30
+ end
31
+
32
+ def coordinates
33
+ [geometry["y"], geometry["x"]]
34
+ end
35
+
36
+ private
37
+
38
+ def attributes
39
+ reverse_geocode? ? @data['address'] : @data['locations'].first['feature']['attributes']
40
+ end
41
+
42
+ def geometry
43
+ reverse_geocode? ? @data["location"] : @data['locations'].first['feature']["geometry"]
44
+ end
45
+
46
+ def reverse_geocode?
47
+ @data['locations'].nil?
48
+ end
49
+
50
+ end
51
+ end
@@ -0,0 +1,45 @@
1
+ require 'geocoder/results/base'
2
+
3
+ module Geocoder::Result
4
+ class Freegeoip < 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_name']
17
+ end
18
+
19
+ def state_code
20
+ @data['region_code']
21
+ end
22
+
23
+ def country
24
+ @data['country_name']
25
+ end
26
+
27
+ def country_code
28
+ @data['country_code']
29
+ end
30
+
31
+ def postal_code
32
+ @data['zipcode']
33
+ end
34
+
35
+ def self.response_attributes
36
+ %w[metrocode ip]
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
@@ -0,0 +1,60 @@
1
+ require 'geocoder/results/base'
2
+
3
+ module Geocoder::Result
4
+ class GeocoderCa < Base
5
+
6
+ def coordinates
7
+ [@data['latt'].to_f, @data['longt'].to_f]
8
+ end
9
+
10
+ def address(format = :full)
11
+ "#{street_address}, #{city}, #{state} #{postal_code}, #{country}".sub(/^[ ,]*/, "")
12
+ end
13
+
14
+ def street_address
15
+ "#{@data['stnumber']} #{@data['staddress']}"
16
+ end
17
+
18
+ def city
19
+ @data['city']
20
+ end
21
+
22
+ def state
23
+ @data['prov']
24
+ end
25
+
26
+ alias_method :state_code, :state
27
+
28
+ def postal_code
29
+ @data['postal']
30
+ end
31
+
32
+ def country
33
+ country_code == 'CA' ? 'Canada' : 'United States'
34
+ end
35
+
36
+ def country_code
37
+ return nil if state.nil? || state == ""
38
+ canadian_province_abbreviations.include?(state) ? "CA" : "US"
39
+ end
40
+
41
+ def self.response_attributes
42
+ %w[latt longt inlatt inlongt distance stnumber staddress prov
43
+ NearRoad NearRoadDistance betweenRoad1 betweenRoad2
44
+ intersection major_intersection]
45
+ end
46
+
47
+ response_attributes.each do |a|
48
+ define_method a do
49
+ @data[a]
50
+ end
51
+ end
52
+
53
+
54
+ private # ----------------------------------------------------------------
55
+
56
+ def canadian_province_abbreviations
57
+ %w[ON QC NS NB MB BC PE SK AB NL]
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,39 @@
1
+ require 'geocoder/results/base'
2
+
3
+ module Geocoder::Result
4
+ class GeocoderUs < Base
5
+ def coordinates
6
+ [@data[0].to_f, @data[1].to_f]
7
+ end
8
+
9
+ def address(format = :full)
10
+ "#{street_address}, #{city}, #{state} #{postal_code}, #{country}".sub(/^[ ,]*/, "")
11
+ end
12
+
13
+ def street_address
14
+ @data[2]
15
+ end
16
+
17
+ def city
18
+ @data[3]
19
+ end
20
+
21
+ def state
22
+ @data[4]
23
+ end
24
+
25
+ alias_method :state_code, :state
26
+
27
+ def postal_code
28
+ @data[5]
29
+ end
30
+
31
+ def country
32
+ 'United States'
33
+ end
34
+
35
+ def country_code
36
+ 'US'
37
+ end
38
+ end
39
+ end