broken-geocoder 1.3.4

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 (119) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +467 -0
  3. data/LICENSE +20 -0
  4. data/README.md +1193 -0
  5. data/bin/geocode +5 -0
  6. data/examples/autoexpire_cache_dalli.rb +62 -0
  7. data/examples/autoexpire_cache_redis.rb +28 -0
  8. data/examples/cache_bypass.rb +48 -0
  9. data/examples/reverse_geocode_job.rb +40 -0
  10. data/lib/generators/geocoder/config/config_generator.rb +14 -0
  11. data/lib/generators/geocoder/config/templates/initializer.rb +21 -0
  12. data/lib/generators/geocoder/maxmind/geolite_city_generator.rb +28 -0
  13. data/lib/generators/geocoder/maxmind/geolite_country_generator.rb +28 -0
  14. data/lib/generators/geocoder/maxmind/templates/migration/geolite_city.rb +30 -0
  15. data/lib/generators/geocoder/maxmind/templates/migration/geolite_country.rb +17 -0
  16. data/lib/geocoder.rb +48 -0
  17. data/lib/geocoder/cache.rb +90 -0
  18. data/lib/geocoder/calculations.rb +431 -0
  19. data/lib/geocoder/cli.rb +121 -0
  20. data/lib/geocoder/configuration.rb +129 -0
  21. data/lib/geocoder/configuration_hash.rb +11 -0
  22. data/lib/geocoder/esri_token.rb +38 -0
  23. data/lib/geocoder/exceptions.rb +37 -0
  24. data/lib/geocoder/ip_address.rb +13 -0
  25. data/lib/geocoder/kernel_logger.rb +25 -0
  26. data/lib/geocoder/logger.rb +47 -0
  27. data/lib/geocoder/lookup.rb +110 -0
  28. data/lib/geocoder/lookups/baidu.rb +59 -0
  29. data/lib/geocoder/lookups/baidu_ip.rb +59 -0
  30. data/lib/geocoder/lookups/base.rb +325 -0
  31. data/lib/geocoder/lookups/bing.rb +80 -0
  32. data/lib/geocoder/lookups/dstk.rb +20 -0
  33. data/lib/geocoder/lookups/esri.rb +64 -0
  34. data/lib/geocoder/lookups/freegeoip.rb +51 -0
  35. data/lib/geocoder/lookups/geocoder_ca.rb +53 -0
  36. data/lib/geocoder/lookups/geocoder_us.rb +43 -0
  37. data/lib/geocoder/lookups/geocodio.rb +42 -0
  38. data/lib/geocoder/lookups/geoip2.rb +45 -0
  39. data/lib/geocoder/lookups/geoportail_lu.rb +65 -0
  40. data/lib/geocoder/lookups/google.rb +91 -0
  41. data/lib/geocoder/lookups/google_places_details.rb +50 -0
  42. data/lib/geocoder/lookups/google_premier.rb +47 -0
  43. data/lib/geocoder/lookups/here.rb +62 -0
  44. data/lib/geocoder/lookups/ipapi_com.rb +86 -0
  45. data/lib/geocoder/lookups/ipinfo_io.rb +55 -0
  46. data/lib/geocoder/lookups/latlon.rb +59 -0
  47. data/lib/geocoder/lookups/mapbox.rb +53 -0
  48. data/lib/geocoder/lookups/mapquest.rb +59 -0
  49. data/lib/geocoder/lookups/mapzen.rb +15 -0
  50. data/lib/geocoder/lookups/maxmind.rb +90 -0
  51. data/lib/geocoder/lookups/maxmind_geoip2.rb +69 -0
  52. data/lib/geocoder/lookups/maxmind_local.rb +65 -0
  53. data/lib/geocoder/lookups/nominatim.rb +52 -0
  54. data/lib/geocoder/lookups/okf.rb +44 -0
  55. data/lib/geocoder/lookups/opencagedata.rb +58 -0
  56. data/lib/geocoder/lookups/ovi.rb +62 -0
  57. data/lib/geocoder/lookups/pelias.rb +64 -0
  58. data/lib/geocoder/lookups/pointpin.rb +68 -0
  59. data/lib/geocoder/lookups/postcode_anywhere_uk.rb +51 -0
  60. data/lib/geocoder/lookups/smarty_streets.rb +50 -0
  61. data/lib/geocoder/lookups/telize.rb +55 -0
  62. data/lib/geocoder/lookups/test.rb +44 -0
  63. data/lib/geocoder/lookups/yandex.rb +58 -0
  64. data/lib/geocoder/models/active_record.rb +50 -0
  65. data/lib/geocoder/models/base.rb +39 -0
  66. data/lib/geocoder/models/mongo_base.rb +62 -0
  67. data/lib/geocoder/models/mongo_mapper.rb +26 -0
  68. data/lib/geocoder/models/mongoid.rb +32 -0
  69. data/lib/geocoder/query.rb +111 -0
  70. data/lib/geocoder/railtie.rb +26 -0
  71. data/lib/geocoder/request.rb +83 -0
  72. data/lib/geocoder/results/baidu.rb +79 -0
  73. data/lib/geocoder/results/baidu_ip.rb +62 -0
  74. data/lib/geocoder/results/base.rb +67 -0
  75. data/lib/geocoder/results/bing.rb +52 -0
  76. data/lib/geocoder/results/dstk.rb +6 -0
  77. data/lib/geocoder/results/esri.rb +75 -0
  78. data/lib/geocoder/results/freegeoip.rb +45 -0
  79. data/lib/geocoder/results/geocoder_ca.rb +60 -0
  80. data/lib/geocoder/results/geocoder_us.rb +39 -0
  81. data/lib/geocoder/results/geocodio.rb +70 -0
  82. data/lib/geocoder/results/geoip2.rb +62 -0
  83. data/lib/geocoder/results/geoportail_lu.rb +69 -0
  84. data/lib/geocoder/results/google.rb +139 -0
  85. data/lib/geocoder/results/google_places_details.rb +35 -0
  86. data/lib/geocoder/results/google_premier.rb +6 -0
  87. data/lib/geocoder/results/here.rb +71 -0
  88. data/lib/geocoder/results/ipapi_com.rb +45 -0
  89. data/lib/geocoder/results/ipinfo_io.rb +48 -0
  90. data/lib/geocoder/results/latlon.rb +71 -0
  91. data/lib/geocoder/results/mapbox.rb +47 -0
  92. data/lib/geocoder/results/mapquest.rb +48 -0
  93. data/lib/geocoder/results/mapzen.rb +5 -0
  94. data/lib/geocoder/results/maxmind.rb +135 -0
  95. data/lib/geocoder/results/maxmind_geoip2.rb +9 -0
  96. data/lib/geocoder/results/maxmind_local.rb +49 -0
  97. data/lib/geocoder/results/nominatim.rb +99 -0
  98. data/lib/geocoder/results/okf.rb +106 -0
  99. data/lib/geocoder/results/opencagedata.rb +90 -0
  100. data/lib/geocoder/results/ovi.rb +71 -0
  101. data/lib/geocoder/results/pelias.rb +58 -0
  102. data/lib/geocoder/results/pointpin.rb +40 -0
  103. data/lib/geocoder/results/postcode_anywhere_uk.rb +42 -0
  104. data/lib/geocoder/results/smarty_streets.rb +106 -0
  105. data/lib/geocoder/results/telize.rb +45 -0
  106. data/lib/geocoder/results/test.rb +33 -0
  107. data/lib/geocoder/results/yandex.rb +92 -0
  108. data/lib/geocoder/sql.rb +107 -0
  109. data/lib/geocoder/stores/active_record.rb +305 -0
  110. data/lib/geocoder/stores/base.rb +116 -0
  111. data/lib/geocoder/stores/mongo_base.rb +58 -0
  112. data/lib/geocoder/stores/mongo_mapper.rb +13 -0
  113. data/lib/geocoder/stores/mongoid.rb +13 -0
  114. data/lib/geocoder/version.rb +3 -0
  115. data/lib/hash_recursive_merge.rb +74 -0
  116. data/lib/maxmind_database.rb +109 -0
  117. data/lib/tasks/geocoder.rake +38 -0
  118. data/lib/tasks/maxmind.rake +73 -0
  119. metadata +167 -0
@@ -0,0 +1,64 @@
1
+ require 'geocoder/lookups/base'
2
+ require 'geocoder/results/pelias'
3
+
4
+ module Geocoder::Lookup
5
+ class Pelias < Base
6
+ def name
7
+ 'Pelias'
8
+ end
9
+
10
+ def endpoint
11
+ configuration[:endpoint] || 'localhost'
12
+ end
13
+
14
+ def query_url(query)
15
+ query_type = query.reverse_geocode? ? 'reverse' : 'search'
16
+ "#{protocol}://#{endpoint}/v1/#{query_type}?" + url_query_string(query)
17
+ end
18
+
19
+ def required_api_key_parts
20
+ ['search-XXXX']
21
+ end
22
+
23
+ private
24
+
25
+ def query_url_params(query)
26
+ params = {
27
+ api_key: configuration.api_key,
28
+ size: 1
29
+ }.merge(super)
30
+
31
+ if query.reverse_geocode?
32
+ lat,lon = query.coordinates
33
+ params[:'point.lat'] = lat
34
+ params[:'point.lon'] = lon
35
+ else
36
+ params[:text] = query.text
37
+ end
38
+ params
39
+ end
40
+
41
+ def results(query)
42
+ return [] unless doc = fetch_data(query)
43
+
44
+ # not all responses include a meta
45
+ if doc['meta']
46
+ error = doc.fetch('results', {}).fetch('error', {})
47
+ message = error.fetch('type', 'Unknown Error') + ': ' + error.fetch('message', 'No message')
48
+ log_message = 'Pelias Geocoding API error - ' + message
49
+ case doc['meta']['status_code']
50
+ when '200'
51
+ # nothing to see here
52
+ when '403'
53
+ raise_error(Geocoder::RequestDenied, message) || Geocoder.log(:warn, log_message)
54
+ when '429'
55
+ raise_error(Geocoder::OverQueryLimitError, message) || Geocoder.log(:warn, log_message)
56
+ else
57
+ raise_error(Geocoder::Error, message) || Geocoder.log(:warn, log_message)
58
+ end
59
+ end
60
+
61
+ doc['features'] || []
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,68 @@
1
+ require 'geocoder/lookups/base'
2
+ require 'geocoder/results/pointpin'
3
+
4
+ module Geocoder::Lookup
5
+ class Pointpin < Base
6
+
7
+ def name
8
+ "Pointpin"
9
+ end
10
+
11
+ def required_api_key_parts
12
+ ["key"]
13
+ end
14
+
15
+ def query_url(query)
16
+ "#{ protocol }://geo.pointp.in/#{ api_key }/json/#{ query.sanitized_text }"
17
+ end
18
+
19
+ private
20
+
21
+ def results(query)
22
+ # don't look up a loopback address, just return the stored result
23
+ return [] if query.loopback_ip_address?
24
+ doc = fetch_data(query)
25
+ if doc and doc.is_a?(Hash)
26
+ if !data_contains_error?(doc)
27
+ return [doc]
28
+ elsif doc['error']
29
+ case doc['error']
30
+ when "Invalid IP address"
31
+ raise_error(Geocoder::InvalidRequest) || Geocoder.log(:warn, "Invalid Pointpin request.")
32
+ when "Invalid API key"
33
+ raise_error(Geocoder::InvalidApiKey) || Geocoder.log(:warn, "Invalid Pointpin API key.")
34
+ when "Address not found"
35
+ Geocoder.log(:warn, "Address not found.")
36
+ end
37
+ else
38
+ raise_error(Geocoder::Error) || Geocoder.log(:warn, "Pointpin server error")
39
+ end
40
+ end
41
+
42
+ return []
43
+ end
44
+
45
+ def data_contains_error?(parsed_data)
46
+ parsed_data.keys.include?('error')
47
+ end
48
+
49
+ def reserved_result(ip)
50
+ {
51
+ "ip" => ip,
52
+ "city" => "",
53
+ "region_code" => "",
54
+ "region_name" => "",
55
+ "metrocode" => "",
56
+ "zipcode" => "",
57
+ "latitude" => "0",
58
+ "longitude" => "0",
59
+ "country_name" => "Reserved",
60
+ "country_code" => "RD"
61
+ }
62
+ end
63
+
64
+ def api_key
65
+ configuration.api_key
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,51 @@
1
+ require 'geocoder/lookups/base'
2
+ require 'geocoder/results/postcode_anywhere_uk'
3
+
4
+ module Geocoder::Lookup
5
+ class PostcodeAnywhereUk < Base
6
+ # API documentation: http://www.postcodeanywhere.co.uk/Support/WebService/Geocoding/UK/Geocode/2/
7
+ BASE_URL_GEOCODE_V2_00 = 'services.postcodeanywhere.co.uk/Geocoding/UK/Geocode/v2.00/json.ws'
8
+ DAILY_LIMIT_EXEEDED_ERROR_CODES = ['8', '17'] # api docs say these two codes are the same error
9
+ INVALID_API_KEY_ERROR_CODE = '2'
10
+
11
+ def name
12
+ 'PostcodeAnywhereUk'
13
+ end
14
+
15
+ def required_api_key_parts
16
+ %w(key)
17
+ end
18
+
19
+ def query_url(query)
20
+ format('%s://%s?%s', protocol, BASE_URL_GEOCODE_V2_00, url_query_string(query))
21
+ end
22
+
23
+ private
24
+
25
+ def results(query)
26
+ response = fetch_data(query)
27
+ return [] if response.nil? || !response.is_a?(Array) || response.empty?
28
+
29
+ raise_exception_for_response(response[0]) if response[0]['Error']
30
+ response
31
+ end
32
+
33
+ def raise_exception_for_response(response)
34
+ case response['Error']
35
+ when *DAILY_LIMIT_EXEEDED_ERROR_CODES
36
+ raise_error(Geocoder::OverQueryLimitError, response['Cause']) || Geocoder.log(:warn, response['Cause'])
37
+ when INVALID_API_KEY_ERROR_CODE
38
+ raise_error(Geocoder::InvalidApiKey, response['Cause']) || Geocoder.log(:warn, response['Cause'])
39
+ else # anything else just raise general error with the api cause
40
+ raise_error(Geocoder::Error, response['Cause']) || Geocoder.log(:warn, response['Cause'])
41
+ end
42
+ end
43
+
44
+ def query_url_params(query)
45
+ {
46
+ :location => query.sanitized_text,
47
+ :key => configuration.api_key
48
+ }.merge(super)
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,50 @@
1
+ require 'geocoder/lookups/base'
2
+ require 'geocoder/results/smarty_streets'
3
+
4
+ module Geocoder::Lookup
5
+ class SmartyStreets < Base
6
+ def name
7
+ "SmartyStreets"
8
+ end
9
+
10
+ def required_api_key_parts
11
+ %w(auti-id auth-token)
12
+ end
13
+
14
+ def query_url(query)
15
+ path = zipcode_only?(query) ? "zipcode" : "street-address"
16
+ "#{protocol}://api.smartystreets.com/#{path}?#{url_query_string(query)}"
17
+ end
18
+
19
+ # required by API as of 26 March 2015
20
+ def supported_protocols
21
+ [:https]
22
+ end
23
+
24
+ private # ---------------------------------------------------------------
25
+
26
+ def zipcode_only?(query)
27
+ !query.text.is_a?(Array) and query.to_s.strip =~ /\A\d{5}(-\d{4})?\Z/
28
+ end
29
+
30
+ def query_url_params(query)
31
+ params = {}
32
+ if zipcode_only?(query)
33
+ params[:zipcode] = query.sanitized_text
34
+ else
35
+ params[:street] = query.sanitized_text
36
+ end
37
+ if configuration.api_key.is_a?(Array)
38
+ params[:"auth-id"] = configuration.api_key[0]
39
+ params[:"auth-token"] = configuration.api_key[1]
40
+ else
41
+ params[:"auth-token"] = configuration.api_key
42
+ end
43
+ params.merge(super)
44
+ end
45
+
46
+ def results(query)
47
+ fetch_data(query) || []
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,55 @@
1
+ require 'geocoder/lookups/base'
2
+ require 'geocoder/results/telize'
3
+
4
+ module Geocoder::Lookup
5
+ class Telize < Base
6
+
7
+ def name
8
+ "Telize"
9
+ end
10
+
11
+ def required_api_key_parts
12
+ configuration[:host] ? [] : ["key"]
13
+ end
14
+
15
+ def query_url(query)
16
+ if configuration[:host]
17
+ "#{protocol}://#{configuration[:host]}/geoip/#{query.sanitized_text}"
18
+ else
19
+ "#{protocol}://telize-v1.p.mashape.com/geoip/#{query.sanitized_text}?mashape-key=#{api_key}"
20
+ end
21
+ end
22
+
23
+ def supported_protocols
24
+ [].tap do |array|
25
+ array << :https
26
+ array << :http if configuration[:host]
27
+ end
28
+ end
29
+
30
+ private # ---------------------------------------------------------------
31
+
32
+ def results(query)
33
+ # don't look up a loopback address, just return the stored result
34
+ return [reserved_result(query.text)] if query.loopback_ip_address?
35
+ if (doc = fetch_data(query)).nil? or doc['code'] == 401 or empty_result?(doc)
36
+ []
37
+ else
38
+ [doc]
39
+ end
40
+ end
41
+
42
+ def empty_result?(doc)
43
+ !doc.is_a?(Hash) or doc.keys == ["ip"]
44
+ end
45
+
46
+ def reserved_result(ip)
47
+ {"message" => "Input string is not a valid IP address", "code" => 401}
48
+ end
49
+
50
+ def api_key
51
+ configuration.api_key
52
+ end
53
+
54
+ end
55
+ end
@@ -0,0 +1,44 @@
1
+ require 'geocoder/lookups/base'
2
+ require 'geocoder/results/test'
3
+
4
+ module Geocoder
5
+ module Lookup
6
+ class Test < Base
7
+
8
+ def name
9
+ "Test"
10
+ end
11
+
12
+ def self.add_stub(query_text, results)
13
+ stubs[query_text] = results
14
+ end
15
+
16
+ def self.set_default_stub(results)
17
+ @default_stub = results
18
+ end
19
+
20
+ def self.read_stub(query_text)
21
+ stubs.fetch(query_text) {
22
+ return @default_stub unless @default_stub.nil?
23
+ raise ArgumentError, "unknown stub request #{query_text}"
24
+ }
25
+ end
26
+
27
+ def self.stubs
28
+ @stubs ||= {}
29
+ end
30
+
31
+ def self.reset
32
+ @stubs = {}
33
+ @default_stub = nil
34
+ end
35
+
36
+ private
37
+
38
+ def results(query)
39
+ Geocoder::Lookup::Test.read_stub(query.text)
40
+ end
41
+
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,58 @@
1
+ require 'geocoder/lookups/base'
2
+ require "geocoder/results/yandex"
3
+
4
+ module Geocoder::Lookup
5
+ class Yandex < Base
6
+
7
+ def name
8
+ "Yandex"
9
+ end
10
+
11
+ def map_link_url(coordinates)
12
+ "http://maps.yandex.ru/?ll=#{coordinates.reverse.join(',')}"
13
+ end
14
+
15
+ def query_url(query)
16
+ "#{protocol}://geocode-maps.yandex.ru/1.x/?" + url_query_string(query)
17
+ end
18
+
19
+ def supported_protocols
20
+ [:https]
21
+ end
22
+
23
+ private # ---------------------------------------------------------------
24
+
25
+ def results(query)
26
+ return [] unless doc = fetch_data(query)
27
+ if err = doc['error']
28
+ if err["status"] == 401 and err["message"] == "invalid key"
29
+ raise_error(Geocoder::InvalidApiKey) || Geocoder.log(:warn, "Invalid API key.")
30
+ else
31
+ Geocoder.log(:warn, "Yandex Geocoding API error: #{err['status']} (#{err['message']}).")
32
+ end
33
+ return []
34
+ end
35
+ if doc = doc['response']['GeoObjectCollection']
36
+ meta = doc['metaDataProperty']['GeocoderResponseMetaData']
37
+ return meta['found'].to_i > 0 ? doc['featureMember'] : []
38
+ else
39
+ Geocoder.log(:warn, "Yandex Geocoding API error: unexpected response format.")
40
+ return []
41
+ end
42
+ end
43
+
44
+ def query_url_params(query)
45
+ if query.reverse_geocode?
46
+ q = query.coordinates.reverse.join(",")
47
+ else
48
+ q = query.sanitized_text
49
+ end
50
+ {
51
+ :geocode => q,
52
+ :format => "json",
53
+ :plng => "#{query.language || configuration.language}", # supports ru, uk, be
54
+ :key => configuration.api_key
55
+ }.merge(super)
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,50 @@
1
+ require 'geocoder/models/base'
2
+
3
+ module Geocoder
4
+ module Model
5
+ module ActiveRecord
6
+ include Base
7
+
8
+ ##
9
+ # Set attribute names and include the Geocoder module.
10
+ #
11
+ def geocoded_by(address_attr, options = {}, &block)
12
+ geocoder_init(
13
+ :geocode => true,
14
+ :user_address => address_attr,
15
+ :latitude => options[:latitude] || :latitude,
16
+ :longitude => options[:longitude] || :longitude,
17
+ :geocode_block => block,
18
+ :units => options[:units],
19
+ :method => options[:method],
20
+ :lookup => options[:lookup],
21
+ :language => options[:language]
22
+ )
23
+ end
24
+
25
+ ##
26
+ # Set attribute names and include the Geocoder module.
27
+ #
28
+ def reverse_geocoded_by(latitude_attr, longitude_attr, options = {}, &block)
29
+ geocoder_init(
30
+ :reverse_geocode => true,
31
+ :fetched_address => options[:address] || :address,
32
+ :latitude => latitude_attr,
33
+ :longitude => longitude_attr,
34
+ :reverse_block => block,
35
+ :units => options[:units],
36
+ :method => options[:method],
37
+ :lookup => options[:lookup],
38
+ :language => options[:language]
39
+ )
40
+ end
41
+
42
+
43
+ private # --------------------------------------------------------------
44
+
45
+ def geocoder_file_name; "active_record"; end
46
+ def geocoder_module_name; "ActiveRecord"; end
47
+ end
48
+ end
49
+ end
50
+