geocoder 1.4.8 → 1.6.0

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 (92) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +31 -0
  3. data/LICENSE +1 -1
  4. data/README.md +355 -950
  5. data/examples/autoexpire_cache_redis.rb +2 -0
  6. data/lib/generators/geocoder/config/templates/initializer.rb +1 -1
  7. data/lib/geocoder/calculations.rb +1 -1
  8. data/lib/geocoder/cli.rb +2 -2
  9. data/lib/geocoder/configuration.rb +1 -1
  10. data/lib/geocoder/exceptions.rb +1 -1
  11. data/lib/geocoder/ip_address.rb +14 -1
  12. data/lib/geocoder/lookup.rb +7 -5
  13. data/lib/geocoder/lookups/amap.rb +7 -3
  14. data/lib/geocoder/lookups/baidu.rb +14 -10
  15. data/lib/geocoder/lookups/baidu_ip.rb +7 -36
  16. data/lib/geocoder/lookups/ban_data_gouv_fr.rb +17 -4
  17. data/lib/geocoder/lookups/base.rb +27 -4
  18. data/lib/geocoder/lookups/bing.rb +10 -13
  19. data/lib/geocoder/lookups/db_ip_com.rb +9 -6
  20. data/lib/geocoder/lookups/dstk.rb +4 -2
  21. data/lib/geocoder/lookups/esri.rb +39 -29
  22. data/lib/geocoder/lookups/freegeoip.rb +11 -7
  23. data/lib/geocoder/lookups/geocoder_ca.rb +4 -4
  24. data/lib/geocoder/lookups/geocodio.rb +5 -5
  25. data/lib/geocoder/lookups/geoportail_lu.rb +7 -7
  26. data/lib/geocoder/lookups/google.rb +8 -8
  27. data/lib/geocoder/lookups/google_places_details.rb +4 -4
  28. data/lib/geocoder/lookups/google_places_search.rb +4 -4
  29. data/lib/geocoder/lookups/google_premier.rb +10 -0
  30. data/lib/geocoder/lookups/here.rb +29 -23
  31. data/lib/geocoder/lookups/ip2location.rb +67 -0
  32. data/lib/geocoder/lookups/ipapi_com.rb +9 -13
  33. data/lib/geocoder/lookups/ipdata_co.rb +9 -4
  34. data/lib/geocoder/lookups/ipgeolocation.rb +63 -0
  35. data/lib/geocoder/lookups/ipinfo_io.rb +11 -29
  36. data/lib/geocoder/lookups/ipregistry.rb +68 -0
  37. data/lib/geocoder/lookups/ipstack.rb +11 -12
  38. data/lib/geocoder/lookups/latlon.rb +4 -4
  39. data/lib/geocoder/lookups/location_iq.rb +10 -4
  40. data/lib/geocoder/lookups/mapbox.rb +7 -6
  41. data/lib/geocoder/lookups/mapquest.rb +4 -5
  42. data/lib/geocoder/lookups/maxmind.rb +6 -6
  43. data/lib/geocoder/lookups/maxmind_geoip2.rb +8 -7
  44. data/lib/geocoder/lookups/nominatim.rb +4 -4
  45. data/lib/geocoder/lookups/opencagedata.rb +6 -5
  46. data/lib/geocoder/lookups/osmnames.rb +57 -0
  47. data/lib/geocoder/lookups/pelias.rb +8 -9
  48. data/lib/geocoder/lookups/pickpoint.rb +9 -3
  49. data/lib/geocoder/lookups/pointpin.rb +10 -9
  50. data/lib/geocoder/lookups/postcode_anywhere_uk.rb +4 -5
  51. data/lib/geocoder/lookups/postcodes_io.rb +31 -0
  52. data/lib/geocoder/lookups/smarty_streets.rb +20 -10
  53. data/lib/geocoder/lookups/telize.rb +23 -3
  54. data/lib/geocoder/lookups/tencent.rb +59 -0
  55. data/lib/geocoder/lookups/yandex.rb +6 -6
  56. data/lib/geocoder/query.rb +14 -0
  57. data/lib/geocoder/railtie.rb +1 -1
  58. data/lib/geocoder/results/baidu.rb +10 -14
  59. data/lib/geocoder/results/ban_data_gouv_fr.rb +1 -1
  60. data/lib/geocoder/results/base.rb +13 -1
  61. data/lib/geocoder/results/bing.rb +1 -1
  62. data/lib/geocoder/results/db_ip_com.rb +0 -5
  63. data/lib/geocoder/results/freegeoip.rb +0 -5
  64. data/lib/geocoder/results/geocoder_ca.rb +3 -3
  65. data/lib/geocoder/results/geoip2.rb +4 -4
  66. data/lib/geocoder/results/geoportail_lu.rb +5 -3
  67. data/lib/geocoder/results/here.rb +4 -1
  68. data/lib/geocoder/results/ip2location.rb +22 -0
  69. data/lib/geocoder/results/ipdata_co.rb +0 -5
  70. data/lib/geocoder/results/ipgeolocation.rb +59 -0
  71. data/lib/geocoder/results/ipregistry.rb +308 -0
  72. data/lib/geocoder/results/maxmind.rb +0 -5
  73. data/lib/geocoder/results/maxmind_local.rb +0 -5
  74. data/lib/geocoder/results/osmnames.rb +56 -0
  75. data/lib/geocoder/results/postcodes_io.rb +40 -0
  76. data/lib/geocoder/results/smarty_streets.rb +48 -18
  77. data/lib/geocoder/results/telize.rb +0 -5
  78. data/lib/geocoder/results/tencent.rb +72 -0
  79. data/lib/geocoder/results/test.rb +1 -1
  80. data/lib/geocoder/stores/active_record.rb +1 -3
  81. data/lib/geocoder/version.rb +1 -1
  82. data/lib/hash_recursive_merge.rb +1 -2
  83. data/lib/maxmind_database.rb +3 -3
  84. metadata +17 -18
  85. data/lib/geocoder/lookups/geocoder_us.rb +0 -43
  86. data/lib/geocoder/lookups/mapzen.rb +0 -15
  87. data/lib/geocoder/lookups/okf.rb +0 -44
  88. data/lib/geocoder/lookups/ovi.rb +0 -62
  89. data/lib/geocoder/results/geocoder_us.rb +0 -39
  90. data/lib/geocoder/results/mapzen.rb +0 -5
  91. data/lib/geocoder/results/okf.rb +0 -106
  92. data/lib/geocoder/results/ovi.rb +0 -71
@@ -12,13 +12,13 @@ module Geocoder::Lookup
12
12
  "https://www.openstreetmap.org/?lat=#{coordinates[0]}&lon=#{coordinates[1]}&zoom=15&layers=M"
13
13
  end
14
14
 
15
- def query_url(query)
15
+ private # ---------------------------------------------------------------
16
+
17
+ def base_query_url(query)
16
18
  method = query.reverse_geocode? ? "reverse" : "search"
17
- "#{protocol}://#{configured_host}/#{method}?" + url_query_string(query)
19
+ "#{protocol}://#{configured_host}/#{method}?"
18
20
  end
19
21
 
20
- private # ---------------------------------------------------------------
21
-
22
22
  def configured_host
23
23
  configuration[:host] || "nominatim.openstreetmap.org"
24
24
  end
@@ -8,15 +8,15 @@ module Geocoder::Lookup
8
8
  "OpenCageData"
9
9
  end
10
10
 
11
- def query_url(query)
12
- "#{protocol}://api.opencagedata.com/geocode/v1/json?key=#{configuration.api_key}&#{url_query_string(query)}"
13
- end
14
-
15
11
  def required_api_key_parts
16
12
  ["key"]
17
13
  end
18
14
 
19
- private
15
+ private # ----------------------------------------------------------------
16
+
17
+ def base_query_url(query)
18
+ "#{protocol}://api.opencagedata.com/geocode/v1/json?"
19
+ end
20
20
 
21
21
  def results(query)
22
22
  return [] unless doc = fetch_data(query)
@@ -44,6 +44,7 @@ module Geocoder::Lookup
44
44
  def query_url_params(query)
45
45
  params = {
46
46
  :q => query.sanitized_text,
47
+ :key => configuration.api_key,
47
48
  :language => (query.language || configuration.language)
48
49
  }.merge(super)
49
50
 
@@ -0,0 +1,57 @@
1
+ require 'cgi'
2
+ require 'geocoder/lookups/base'
3
+ require 'geocoder/results/osmnames'
4
+
5
+ module Geocoder::Lookup
6
+ class Osmnames < Base
7
+
8
+ def name
9
+ 'OSM Names'
10
+ end
11
+
12
+ def required_api_key_parts
13
+ configuration[:host] ? [] : ['key']
14
+ end
15
+
16
+ def supported_protocols
17
+ [:https]
18
+ end
19
+
20
+ private
21
+
22
+ def base_query_url(query)
23
+ "#{base_url(query)}/#{params_url(query)}.js?"
24
+ end
25
+
26
+ def base_url(query)
27
+ host = configuration[:host] || 'geocoder.tilehosting.com'
28
+ "#{protocol}://#{host}"
29
+ end
30
+
31
+ def params_url(query)
32
+ method, args = 'q', CGI.escape(query.sanitized_text)
33
+ method, args = 'r', query.coordinates.join('/') if query.reverse_geocode?
34
+ "#{country_limited(query)}#{method}/#{args}"
35
+ end
36
+
37
+ def results(query)
38
+ return [] unless doc = fetch_data(query)
39
+ if (error = doc['message'])
40
+ raise_error(Geocoder::InvalidRequest, error) ||
41
+ Geocoder.log(:warn, "OSMNames Geocoding API error: #{error}")
42
+ else
43
+ return doc['results']
44
+ end
45
+ end
46
+
47
+ def query_url_params(query)
48
+ {
49
+ key: configuration.api_key
50
+ }.merge(super)
51
+ end
52
+
53
+ def country_limited(query)
54
+ "#{query.options[:country_code].downcase}/" if query.options[:country_code] && !query.reverse_geocode?
55
+ end
56
+ end
57
+ end
@@ -11,25 +11,24 @@ module Geocoder::Lookup
11
11
  configuration[:endpoint] || 'localhost'
12
12
  end
13
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
14
  def required_api_key_parts
20
15
  ['search-XXXX']
21
16
  end
22
17
 
23
- private
18
+ private # ----------------------------------------------------------------
19
+
20
+ def base_query_url(query)
21
+ query_type = query.reverse_geocode? ? 'reverse' : 'search'
22
+ "#{protocol}://#{endpoint}/v1/#{query_type}?"
23
+ end
24
24
 
25
25
  def query_url_params(query)
26
26
  params = {
27
- api_key: configuration.api_key,
28
- size: 1
27
+ api_key: configuration.api_key
29
28
  }.merge(super)
30
29
 
31
30
  if query.reverse_geocode?
32
- lat,lon = query.coordinates
31
+ lat, lon = query.coordinates
33
32
  params[:'point.lat'] = lat
34
33
  params[:'point.lon'] = lon
35
34
  else
@@ -15,12 +15,18 @@ module Geocoder::Lookup
15
15
  ["api_key"]
16
16
  end
17
17
 
18
- def query_url(query)
18
+ private # ----------------------------------------------------------------
19
+
20
+ def base_query_url(query)
19
21
  method = query.reverse_geocode? ? "reverse" : "forward"
20
- "#{protocol}://api.pickpoint.io/v1/#{method}?key=#{configuration.api_key}&" + url_query_string(query)
22
+ "#{protocol}://api.pickpoint.io/v1/#{method}?"
21
23
  end
22
24
 
23
- private
25
+ def query_url_params(query)
26
+ {
27
+ key: configuration.api_key
28
+ }.merge(super)
29
+ end
24
30
 
25
31
  def results(query)
26
32
  return [] unless doc = fetch_data(query)
@@ -13,14 +13,18 @@ module Geocoder::Lookup
13
13
  end
14
14
 
15
15
  def query_url(query)
16
- "#{ protocol }://geo.pointp.in/#{ api_key }/json/#{ query.sanitized_text }"
16
+ "#{protocol}://geo.pointp.in/#{configuration.api_key}/json/#{query.sanitized_text}"
17
17
  end
18
18
 
19
- private
19
+ private # ----------------------------------------------------------------
20
+
21
+ def cache_key(query)
22
+ "#{protocol}://geo.pointp.in/json/#{query.sanitized_text}"
23
+ end
20
24
 
21
25
  def results(query)
22
- # don't look up a loopback address, just return the stored result
23
- return [] if query.loopback_ip_address?
26
+ # don't look up a loopback or private address, just return the stored result
27
+ return [] if query.internal_ip_address?
24
28
  doc = fetch_data(query)
25
29
  if doc and doc.is_a?(Hash)
26
30
  if !data_contains_error?(doc)
@@ -38,7 +42,7 @@ module Geocoder::Lookup
38
42
  raise_error(Geocoder::Error) || Geocoder.log(:warn, "Pointpin server error")
39
43
  end
40
44
  end
41
-
45
+
42
46
  return []
43
47
  end
44
48
 
@@ -46,6 +50,7 @@ module Geocoder::Lookup
46
50
  parsed_data.keys.include?('error')
47
51
  end
48
52
 
53
+ # TODO: replace this hash with what's actually returned by Pointpin
49
54
  def reserved_result(ip)
50
55
  {
51
56
  "ip" => ip,
@@ -60,9 +65,5 @@ module Geocoder::Lookup
60
65
  "country_code" => "RD"
61
66
  }
62
67
  end
63
-
64
- def api_key
65
- configuration.api_key
66
- end
67
68
  end
68
69
  end
@@ -4,7 +4,6 @@ require 'geocoder/results/postcode_anywhere_uk'
4
4
  module Geocoder::Lookup
5
5
  class PostcodeAnywhereUk < Base
6
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
7
  DAILY_LIMIT_EXEEDED_ERROR_CODES = ['8', '17'] # api docs say these two codes are the same error
9
8
  INVALID_API_KEY_ERROR_CODE = '2'
10
9
 
@@ -16,11 +15,11 @@ module Geocoder::Lookup
16
15
  %w(key)
17
16
  end
18
17
 
19
- def query_url(query)
20
- format('%s://%s?%s', protocol, BASE_URL_GEOCODE_V2_00, url_query_string(query))
21
- end
18
+ private # ----------------------------------------------------------------
22
19
 
23
- private
20
+ def base_query_url(query)
21
+ "#{protocol}://services.postcodeanywhere.co.uk/Geocoding/UK/Geocode/v2.00/json.ws?"
22
+ end
24
23
 
25
24
  def results(query)
26
25
  response = fetch_data(query)
@@ -0,0 +1,31 @@
1
+ require 'geocoder/lookups/base'
2
+ require 'geocoder/results/postcodes_io'
3
+
4
+ module Geocoder::Lookup
5
+ class PostcodesIo < Base
6
+ def name
7
+ 'Postcodes.io'
8
+ end
9
+
10
+ def query_url(query)
11
+ "#{protocol}://api.postcodes.io/postcodes/#{query.sanitized_text.gsub(/\s/, '')}"
12
+ end
13
+
14
+ def supported_protocols
15
+ [:https]
16
+ end
17
+
18
+ private # ----------------------------------------------------------------
19
+
20
+ def cache_key(query)
21
+ query_url(query)
22
+ end
23
+
24
+ def results(query)
25
+ response = fetch_data(query)
26
+ return [] if response.nil? || response['status'] != 200 || response.empty?
27
+
28
+ [response['result']]
29
+ end
30
+ end
31
+ end
@@ -8,15 +8,7 @@ module Geocoder::Lookup
8
8
  end
9
9
 
10
10
  def required_api_key_parts
11
- %w(auti-id auth-token)
12
- end
13
-
14
- def query_url(query)
15
- if zipcode_only?(query)
16
- "#{protocol}://us-zipcode.api.smartystreets.com/lookup?#{url_query_string(query)}"
17
- else
18
- "#{protocol}://us-street.api.smartystreets.com/street-address?#{url_query_string(query)}"
19
- end
11
+ %w(auth-id auth-token)
20
12
  end
21
13
 
22
14
  # required by API as of 26 March 2015
@@ -26,13 +18,31 @@ module Geocoder::Lookup
26
18
 
27
19
  private # ---------------------------------------------------------------
28
20
 
21
+ def base_query_url(query)
22
+ if international?(query)
23
+ "#{protocol}://international-street.api.smartystreets.com/verify?"
24
+ elsif zipcode_only?(query)
25
+ "#{protocol}://us-zipcode.api.smartystreets.com/lookup?"
26
+ else
27
+ "#{protocol}://us-street.api.smartystreets.com/street-address?"
28
+ end
29
+ end
30
+
29
31
  def zipcode_only?(query)
30
32
  !query.text.is_a?(Array) and query.to_s.strip =~ /\A\d{5}(-\d{4})?\Z/
31
33
  end
32
34
 
35
+ def international?(query)
36
+ !query.options[:country].nil?
37
+ end
38
+
33
39
  def query_url_params(query)
34
40
  params = {}
35
- if zipcode_only?(query)
41
+ if international?(query)
42
+ params[:freeform] = query.sanitized_text
43
+ params[:country] = query.options[:country]
44
+ params[:geocode] = true
45
+ elsif zipcode_only?(query)
36
46
  params[:zipcode] = query.sanitized_text
37
47
  else
38
48
  params[:street] = query.sanitized_text
@@ -29,9 +29,13 @@ module Geocoder::Lookup
29
29
 
30
30
  private # ---------------------------------------------------------------
31
31
 
32
+ def cache_key(query)
33
+ query_url(query)[/(.*)\?.*/, 1]
34
+ end
35
+
32
36
  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?
37
+ # don't look up a loopback or private address, just return the stored result
38
+ return [reserved_result(query.text)] if query.internal_ip_address?
35
39
  if (doc = fetch_data(query)).nil? or doc['code'] == 401 or empty_result?(doc)
36
40
  []
37
41
  else
@@ -44,7 +48,23 @@ module Geocoder::Lookup
44
48
  end
45
49
 
46
50
  def reserved_result(ip)
47
- {"message" => "Input string is not a valid IP address", "code" => 401}
51
+ {
52
+ "ip" => ip,
53
+ "latitude" => 0,
54
+ "longitude" => 0,
55
+ "city" => "",
56
+ "timezone" => "",
57
+ "asn" => 0,
58
+ "region" => "",
59
+ "offset" => 0,
60
+ "organization" => "",
61
+ "country_code" => "",
62
+ "country_code3" => "",
63
+ "postal_code" => "",
64
+ "continent_code" => "",
65
+ "country" => "",
66
+ "region_code" => ""
67
+ }
48
68
  end
49
69
 
50
70
  def api_key
@@ -0,0 +1,59 @@
1
+ require 'geocoder/lookups/base'
2
+ require "geocoder/results/tencent"
3
+
4
+ module Geocoder::Lookup
5
+ class Tencent < Base
6
+
7
+ def name
8
+ "Tencent"
9
+ end
10
+
11
+ def required_api_key_parts
12
+ ["key"]
13
+ end
14
+
15
+ def supported_protocols
16
+ [:https]
17
+ end
18
+
19
+ private # ---------------------------------------------------------------
20
+
21
+ def base_query_url(query)
22
+ "#{protocol}://apis.map.qq.com/ws/geocoder/v1/?"
23
+ end
24
+
25
+ def content_key
26
+ 'result'
27
+ end
28
+
29
+ def results(query, reverse = false)
30
+ return [] unless doc = fetch_data(query)
31
+ case doc['status']
32
+ when 0
33
+ return [doc[content_key]]
34
+ when 311
35
+ raise_error(Geocoder::InvalidApiKey, "invalid api key") ||
36
+ Geocoder.log(:warn, "#{name} Geocoding API error: invalid api key.")
37
+ when 310
38
+ raise_error(Geocoder::InvalidRequest, "invalid request.") ||
39
+ Geocoder.log(:warn, "#{name} Geocoding API error: invalid request, invalid parameters.")
40
+ when 306
41
+ raise_error(Geocoder::InvalidRequest, "invalid request.") ||
42
+ Geocoder.log(:warn, "#{name} Geocoding API error: invalid request, check response for more info.")
43
+ when 110
44
+ raise_error(Geocoder::RequestDenied, "request denied.") ||
45
+ Geocoder.log(:warn, "#{name} Geocoding API error: request source is not authorized.")
46
+ end
47
+ return []
48
+ end
49
+
50
+ def query_url_params(query)
51
+ {
52
+ (query.reverse_geocode? ? :location : :address) => query.sanitized_text,
53
+ :key => configuration.api_key,
54
+ :output => "json"
55
+ }.merge(super)
56
+ end
57
+
58
+ end
59
+ end
@@ -12,16 +12,16 @@ module Geocoder::Lookup
12
12
  "http://maps.yandex.ru/?ll=#{coordinates.reverse.join(',')}"
13
13
  end
14
14
 
15
- def query_url(query)
16
- "#{protocol}://geocode-maps.yandex.ru/1.x/?" + url_query_string(query)
17
- end
18
-
19
15
  def supported_protocols
20
16
  [:https]
21
17
  end
22
18
 
23
19
  private # ---------------------------------------------------------------
24
20
 
21
+ def base_query_url(query)
22
+ "#{protocol}://geocode-maps.yandex.ru/1.x/?"
23
+ end
24
+
25
25
  def results(query)
26
26
  return [] unless doc = fetch_data(query)
27
27
  if err = doc['error']
@@ -50,8 +50,8 @@ module Geocoder::Lookup
50
50
  params = {
51
51
  :geocode => q,
52
52
  :format => "json",
53
- :plng => "#{query.language || configuration.language}", # supports ru, uk, be
54
- :key => configuration.api_key
53
+ :lang => "#{query.language || configuration.language}", # supports ru, uk, be, default -> ru
54
+ :apikey => configuration.api_key
55
55
  }
56
56
  unless (bounds = query.options[:bounds]).nil?
57
57
  params[:bbox] = bounds.map{ |point| "%f,%f" % point }.join('~')