geocoder 1.4.7 → 1.5.2

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 (86) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +31 -0
  3. data/README.md +352 -935
  4. data/examples/autoexpire_cache_redis.rb +3 -3
  5. data/lib/generators/geocoder/config/templates/initializer.rb +2 -2
  6. data/lib/geocoder/cache.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 +2 -2
  10. data/lib/geocoder/exceptions.rb +1 -1
  11. data/lib/geocoder/ip_address.rb +14 -1
  12. data/lib/geocoder/lookup.rb +6 -4
  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 +4 -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/geocoder_us.rb +17 -9
  25. data/lib/geocoder/lookups/geocodio.rb +5 -5
  26. data/lib/geocoder/lookups/geoportail_lu.rb +7 -7
  27. data/lib/geocoder/lookups/google.rb +8 -8
  28. data/lib/geocoder/lookups/google_places_details.rb +4 -4
  29. data/lib/geocoder/lookups/google_places_search.rb +4 -4
  30. data/lib/geocoder/lookups/google_premier.rb +10 -0
  31. data/lib/geocoder/lookups/here.rb +30 -15
  32. data/lib/geocoder/lookups/ip2location.rb +75 -0
  33. data/lib/geocoder/lookups/ipapi_com.rb +9 -13
  34. data/lib/geocoder/lookups/ipdata_co.rb +9 -4
  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 +63 -0
  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/pelias.rb +8 -9
  47. data/lib/geocoder/lookups/pickpoint.rb +9 -3
  48. data/lib/geocoder/lookups/pointpin.rb +10 -9
  49. data/lib/geocoder/lookups/postcode_anywhere_uk.rb +4 -5
  50. data/lib/geocoder/lookups/postcodes_io.rb +31 -0
  51. data/lib/geocoder/lookups/smarty_streets.rb +20 -10
  52. data/lib/geocoder/lookups/telize.rb +26 -6
  53. data/lib/geocoder/lookups/tencent.rb +59 -0
  54. data/lib/geocoder/lookups/yandex.rb +6 -6
  55. data/lib/geocoder/query.rb +14 -0
  56. data/lib/geocoder/railtie.rb +1 -1
  57. data/lib/geocoder/results/baidu.rb +10 -10
  58. data/lib/geocoder/results/base.rb +13 -1
  59. data/lib/geocoder/results/bing.rb +1 -1
  60. data/lib/geocoder/results/db_ip_com.rb +0 -5
  61. data/lib/geocoder/results/freegeoip.rb +0 -5
  62. data/lib/geocoder/results/geocoder_ca.rb +3 -3
  63. data/lib/geocoder/results/geoip2.rb +2 -6
  64. data/lib/geocoder/results/geoportail_lu.rb +5 -3
  65. data/lib/geocoder/results/here.rb +4 -1
  66. data/lib/geocoder/results/ip2location.rb +22 -0
  67. data/lib/geocoder/results/ipdata_co.rb +0 -5
  68. data/lib/geocoder/results/ipregistry.rb +308 -0
  69. data/lib/geocoder/results/ipstack.rb +60 -0
  70. data/lib/geocoder/results/maxmind.rb +0 -5
  71. data/lib/geocoder/results/maxmind_local.rb +0 -5
  72. data/lib/geocoder/results/postcodes_io.rb +40 -0
  73. data/lib/geocoder/results/smarty_streets.rb +48 -18
  74. data/lib/geocoder/results/telize.rb +0 -5
  75. data/lib/geocoder/results/tencent.rb +72 -0
  76. data/lib/geocoder/results/test.rb +1 -1
  77. data/lib/geocoder/stores/active_record.rb +1 -3
  78. data/lib/geocoder/stores/base.rb +1 -1
  79. data/lib/geocoder/version.rb +1 -1
  80. metadata +14 -10
  81. data/lib/geocoder/lookups/mapzen.rb +0 -15
  82. data/lib/geocoder/lookups/okf.rb +0 -44
  83. data/lib/geocoder/lookups/ovi.rb +0 -62
  84. data/lib/geocoder/results/mapzen.rb +0 -5
  85. data/lib/geocoder/results/okf.rb +0 -106
  86. data/lib/geocoder/results/ovi.rb +0 -71
@@ -4,15 +4,11 @@ require 'geocoder/esri_token'
4
4
 
5
5
  module Geocoder::Lookup
6
6
  class Esri < Base
7
-
7
+
8
8
  def name
9
9
  "Esri"
10
10
  end
11
11
 
12
- def query_url(query)
13
- base_query_url(query) + url_query_string(query)
14
- end
15
-
16
12
  private # ---------------------------------------------------------------
17
13
 
18
14
  def base_query_url(query)
@@ -34,17 +30,6 @@ module Geocoder::Lookup
34
30
  end
35
31
  end
36
32
 
37
- def cache_key(query)
38
- base_query_url(query) + hash_to_query(cache_key_params(query))
39
- end
40
-
41
- def cache_key_params(query)
42
- # omit api_key and token because they may vary among requests
43
- query_url_params(query).reject do |key,value|
44
- [:api_key, :token].include?(key)
45
- end
46
- end
47
-
48
33
  def query_url_params(query)
49
34
  params = {
50
35
  :f => "pjson",
@@ -55,31 +40,56 @@ module Geocoder::Lookup
55
40
  else
56
41
  params[:text] = query.sanitized_text
57
42
  end
58
- params[:token] = token
59
- params[:forStorage] = configuration[:for_storage] if configuration[:for_storage]
43
+
44
+ params[:token] = token(query)
45
+
46
+ if for_storage_value = for_storage(query)
47
+ params[:forStorage] = for_storage_value
48
+ end
60
49
  params[:sourceCountry] = configuration[:source_country] if configuration[:source_country]
61
50
  params.merge(super)
62
51
  end
63
52
 
64
- def token
65
- create_and_save_token! if !valid_token_configured? and configuration.api_key
66
- configuration[:token].to_s unless configuration[:token].nil?
53
+ def for_storage(query)
54
+ if query.options.has_key?(:for_storage)
55
+ query.options[:for_storage]
56
+ else
57
+ configuration[:for_storage]
58
+ end
59
+ end
60
+
61
+ def token(query)
62
+ token_instance = if query.options[:token]
63
+ query.options[:token]
64
+ else
65
+ configuration[:token]
66
+ end
67
+
68
+ if !valid_token_configured?(token_instance) && configuration.api_key
69
+ token_instance = create_and_save_token!(query)
70
+ end
71
+
72
+ token_instance.to_s unless token_instance.nil?
67
73
  end
68
74
 
69
- def valid_token_configured?
70
- !configuration[:token].nil? and configuration[:token].active?
75
+ def valid_token_configured?(token_instance)
76
+ !token_instance.nil? && token_instance.active?
71
77
  end
72
78
 
73
- def create_and_save_token!
74
- save_token!(create_token)
79
+ def create_and_save_token!(query)
80
+ token_instance = create_token
81
+
82
+ if query.options[:token]
83
+ query.options[:token] = token_instance
84
+ else
85
+ Geocoder.merge_into_lookup_config(:esri, token: token_instance)
86
+ end
87
+
88
+ token_instance
75
89
  end
76
90
 
77
91
  def create_token
78
92
  Geocoder::EsriToken.generate_token(*configuration.api_key)
79
93
  end
80
-
81
- def save_token!(token_instance)
82
- Geocoder.merge_into_lookup_config(:esri, token: token_instance)
83
- end
84
94
  end
85
95
  end
@@ -7,10 +7,10 @@ module Geocoder::Lookup
7
7
  def name
8
8
  "FreeGeoIP"
9
9
  end
10
-
10
+
11
11
  def supported_protocols
12
12
  if configuration[:host]
13
- [:http, :https]
13
+ [:https]
14
14
  else
15
15
  # use https for default host
16
16
  [:https]
@@ -23,13 +23,17 @@ module Geocoder::Lookup
23
23
 
24
24
  private # ---------------------------------------------------------------
25
25
 
26
+ def cache_key(query)
27
+ query_url(query)
28
+ end
29
+
26
30
  def parse_raw_data(raw_data)
27
31
  raw_data.match(/^<html><title>404/) ? nil : super(raw_data)
28
32
  end
29
33
 
30
34
  def results(query)
31
- # don't look up a loopback address, just return the stored result
32
- return [reserved_result(query.text)] if query.loopback_ip_address?
35
+ # don't look up a loopback or private address, just return the stored result
36
+ return [reserved_result(query.text)] if query.internal_ip_address?
33
37
  # note: Freegeoip.net returns plain text "Not Found" on bad request
34
38
  (doc = fetch_data(query)) ? [doc] : []
35
39
  end
@@ -40,8 +44,8 @@ module Geocoder::Lookup
40
44
  "city" => "",
41
45
  "region_code" => "",
42
46
  "region_name" => "",
43
- "metrocode" => "",
44
- "zipcode" => "",
47
+ "metro_code" => "",
48
+ "zip_code" => "",
45
49
  "latitude" => "0",
46
50
  "longitude" => "0",
47
51
  "country_name" => "Reserved",
@@ -50,7 +54,7 @@ module Geocoder::Lookup
50
54
  end
51
55
 
52
56
  def host
53
- configuration[:host] || "freegeoip.net"
57
+ configuration[:host] || "freegeoip.app"
54
58
  end
55
59
  end
56
60
  end
@@ -8,12 +8,12 @@ module Geocoder::Lookup
8
8
  "Geocoder.ca"
9
9
  end
10
10
 
11
- def query_url(query)
12
- "#{protocol}://geocoder.ca/?" + url_query_string(query)
13
- end
14
-
15
11
  private # ---------------------------------------------------------------
16
12
 
13
+ def base_query_url(query)
14
+ "#{protocol}://geocoder.ca/?"
15
+ end
16
+
17
17
  def results(query)
18
18
  return [] unless doc = fetch_data(query)
19
19
  if doc['error'].nil?
@@ -8,20 +8,28 @@ module Geocoder::Lookup
8
8
  "Geocoder.us"
9
9
  end
10
10
 
11
- def supported_protocols
12
- [:http]
13
- end
11
+ def supported_protocols
12
+ [:http]
13
+ end
14
+
15
+ private # ----------------------------------------------------------------
16
+
17
+ def base_query_url(query)
18
+ base_query_url_with_optional_key(configuration.api_key)
19
+ end
14
20
 
15
- def query_url(query)
21
+ def cache_key(query)
22
+ base_query_url_with_optional_key(nil) + url_query_string(query)
23
+ end
24
+
25
+ def base_query_url_with_optional_key(key = nil)
26
+ base = "#{protocol}://"
16
27
  if configuration.api_key
17
- "#{protocol}://#{configuration.api_key}@geocoder.us/member/service/csv/geocode?" + url_query_string(query)
18
- else
19
- "#{protocol}://geocoder.us/service/csv/geocode?" + url_query_string(query)
28
+ base << "#{configuration.api_key}@"
20
29
  end
30
+ base + "geocoder.us/member/service/csv/geocode?"
21
31
  end
22
32
 
23
- private
24
-
25
33
  def results(query)
26
34
  return [] unless doc = fetch_data(query)
27
35
  if doc[0].to_s =~ /^(\d+)\:/
@@ -8,11 +8,6 @@ module Geocoder::Lookup
8
8
  "Geocodio"
9
9
  end
10
10
 
11
- def query_url(query)
12
- path = query.reverse_geocode? ? "reverse" : "geocode"
13
- "#{protocol}://api.geocod.io/v1.2/#{path}?#{url_query_string(query)}"
14
- end
15
-
16
11
  def results(query)
17
12
  return [] unless doc = fetch_data(query)
18
13
  return doc["results"] if doc['error'].nil?
@@ -32,6 +27,11 @@ module Geocoder::Lookup
32
27
 
33
28
  private # ---------------------------------------------------------------
34
29
 
30
+ def base_query_url(query)
31
+ path = query.reverse_geocode? ? "reverse" : "geocode"
32
+ "#{protocol}://api.geocod.io/v1.3/#{path}?"
33
+ end
34
+
35
35
  def query_url_params(query)
36
36
  {
37
37
  :api_key => configuration.api_key,
@@ -9,14 +9,14 @@ module Geocoder
9
9
  "Geoportail.lu"
10
10
  end
11
11
 
12
- def query_url(query)
13
- url_base_path(query) + url_query_string(query)
14
- end
15
-
16
- private
12
+ private # ---------------------------------------------------------------
17
13
 
18
- def url_base_path(query)
19
- query.reverse_geocode? ? reverse_geocode_url_base_path : search_url_base_path
14
+ def base_query_url(query)
15
+ if query.reverse_geocode?
16
+ reverse_geocode_url_base_path
17
+ else
18
+ search_url_base_path
19
+ end
20
20
  end
21
21
 
22
22
  def search_url_base_path
@@ -21,12 +21,12 @@ module Geocoder::Lookup
21
21
  end
22
22
  end
23
23
 
24
- def query_url(query)
25
- "#{protocol}://maps.googleapis.com/maps/api/geocode/json?" + url_query_string(query)
26
- end
27
-
28
24
  private # ---------------------------------------------------------------
29
25
 
26
+ def base_query_url(query)
27
+ "#{protocol}://maps.googleapis.com/maps/api/geocode/json?"
28
+ end
29
+
30
30
  def configure_ssl!(client)
31
31
  client.instance_eval {
32
32
  @ssl_context = OpenSSL::SSL::SSLContext.new
@@ -52,11 +52,11 @@ module Geocoder::Lookup
52
52
  raise_error(Geocoder::OverQueryLimitError) ||
53
53
  Geocoder.log(:warn, "#{name} API error: over query limit.")
54
54
  when "REQUEST_DENIED"
55
- raise_error(Geocoder::RequestDenied) ||
56
- Geocoder.log(:warn, "#{name} API error: request denied.")
55
+ raise_error(Geocoder::RequestDenied, doc['error_message']) ||
56
+ Geocoder.log(:warn, "#{name} API error: request denied (#{doc['error_message']}).")
57
57
  when "INVALID_REQUEST"
58
- raise_error(Geocoder::InvalidRequest) ||
59
- Geocoder.log(:warn, "#{name} API error: invalid request.")
58
+ raise_error(Geocoder::InvalidRequest, doc['error_message']) ||
59
+ Geocoder.log(:warn, "#{name} API error: invalid request (#{doc['error_message']}).")
60
60
  end
61
61
  return []
62
62
  end
@@ -16,12 +16,12 @@ module Geocoder
16
16
  [:https]
17
17
  end
18
18
 
19
- def query_url(query)
20
- "#{protocol}://maps.googleapis.com/maps/api/place/details/json?#{url_query_string(query)}"
21
- end
22
-
23
19
  private
24
20
 
21
+ def base_query_url(query)
22
+ "#{protocol}://maps.googleapis.com/maps/api/place/details/json?"
23
+ end
24
+
25
25
  def results(query)
26
26
  return [] unless doc = fetch_data(query)
27
27
 
@@ -16,12 +16,12 @@ module Geocoder
16
16
  [:https]
17
17
  end
18
18
 
19
- def query_url(query)
20
- "#{protocol}://maps.googleapis.com/maps/api/place/textsearch/json?#{url_query_string(query)}"
21
- end
22
-
23
19
  private
24
20
 
21
+ def base_query_url(query)
22
+ "#{protocol}://maps.googleapis.com/maps/api/place/textsearch/json?"
23
+ end
24
+
25
25
  def query_url_google_params(query)
26
26
  {
27
27
  query: query.text,
@@ -21,6 +21,16 @@ module Geocoder::Lookup
21
21
 
22
22
  private # ---------------------------------------------------------------
23
23
 
24
+ def cache_key(query)
25
+ "#{protocol}://maps.googleapis.com/maps/api/geocode/json?" + hash_to_query(cache_key_params(query))
26
+ end
27
+
28
+ def cache_key_params(query)
29
+ query_url_google_params(query).merge(super).reject do |k,v|
30
+ [:key, :client, :channel].include?(k)
31
+ end
32
+ end
33
+
24
34
  def query_url_params(query)
25
35
  query_url_google_params(query).merge(super).merge(
26
36
  :key => nil, # don't use param inherited from Google lookup
@@ -12,12 +12,12 @@ module Geocoder::Lookup
12
12
  ["app_id", "app_code"]
13
13
  end
14
14
 
15
- def query_url(query)
16
- "#{protocol}://#{if query.reverse_geocode? then 'reverse.' end}geocoder.api.here.com/6.2/#{if query.reverse_geocode? then 'reverse' end}geocode.json?" + url_query_string(query)
17
- end
18
-
19
15
  private # ---------------------------------------------------------------
20
16
 
17
+ def base_query_url(query)
18
+ "#{protocol}://#{if query.reverse_geocode? then 'reverse.' end}geocoder.api.here.com/6.2/#{if query.reverse_geocode? then 'reverse' end}geocode.json?"
19
+ end
20
+
21
21
  def results(query)
22
22
  return [] unless doc = fetch_data(query)
23
23
  return [] unless doc['Response'] && doc['Response']['View']
@@ -28,33 +28,48 @@ module Geocoder::Lookup
28
28
  []
29
29
  end
30
30
 
31
- def query_url_params(query)
31
+ def query_url_here_options(query, reverse_geocode)
32
32
  options = {
33
- :gen=>4,
34
- :app_id=>api_key,
35
- :app_code=>api_code
33
+ gen: 9,
34
+ app_id: api_key,
35
+ app_code: api_code,
36
+ language: (query.language || configuration.language)
36
37
  }
38
+ if reverse_geocode
39
+ options[:mode] = :retrieveAddresses
40
+ return options
41
+ end
37
42
 
43
+ unless (country = query.options[:country]).nil?
44
+ options[:country] = country
45
+ end
46
+
47
+ unless (mapview = query.options[:bounds]).nil?
48
+ options[:mapview] = mapview.map{ |point| "%f,%f" % point }.join(';')
49
+ end
50
+ options
51
+ end
52
+
53
+ def query_url_params(query)
38
54
  if query.reverse_geocode?
39
- super.merge(options).merge(
40
- :prox=>query.sanitized_text,
41
- :mode=>:retrieveAddresses
55
+ super.merge(query_url_here_options(query, true)).merge(
56
+ prox: query.sanitized_text
42
57
  )
43
58
  else
44
- super.merge(options).merge(
45
- :searchtext=>query.sanitized_text
59
+ super.merge(query_url_here_options(query, false)).merge(
60
+ searchtext: query.sanitized_text
46
61
  )
47
62
  end
48
63
  end
49
64
 
50
65
  def api_key
51
- if a=configuration.api_key
66
+ if (a = configuration.api_key)
52
67
  return a.first if a.is_a?(Array)
53
68
  end
54
69
  end
55
70
 
56
71
  def api_code
57
- if a=configuration.api_key
72
+ if (a = configuration.api_key)
58
73
  return a.last if a.is_a?(Array)
59
74
  end
60
75
  end
@@ -0,0 +1,75 @@
1
+ require 'geocoder/lookups/base'
2
+ require 'geocoder/results/ip2location'
3
+
4
+ module Geocoder::Lookup
5
+ class Ip2location < Base
6
+
7
+ def name
8
+ "IP2LocationApi"
9
+ end
10
+
11
+ def supported_protocols
12
+ [:http, :https]
13
+ end
14
+
15
+ private # ----------------------------------------------------------------
16
+
17
+ def base_query_url(query)
18
+ "#{protocol}://api.ip2location.com/?"
19
+ end
20
+
21
+ def query_url_params(query)
22
+ {
23
+ key: configuration.api_key ? configuration.api_key : "demo",
24
+ format: "json",
25
+ ip: query.sanitized_text
26
+ }.merge(super)
27
+ end
28
+
29
+ def results(query)
30
+ # don't look up a loopback or private address, just return the stored result
31
+ return [reserved_result(query.text)] if query.internal_ip_address?
32
+ return [] unless doc = fetch_data(query)
33
+ if doc["response"] == "INVALID ACCOUNT"
34
+ raise_error(Geocoder::InvalidApiKey) || Geocoder.log(:warn, "INVALID ACCOUNT")
35
+ return []
36
+ else
37
+ return [doc]
38
+ end
39
+ end
40
+
41
+ def reserved_result(query)
42
+ {
43
+ "country_code" => "INVALID IP ADDRESS",
44
+ "country_name" => "INVALID IP ADDRESS",
45
+ "region_name" => "INVALID IP ADDRESS",
46
+ "city_name" => "INVALID IP ADDRESS",
47
+ "latitude" => "INVALID IP ADDRESS",
48
+ "longitude" => "INVALID IP ADDRESS",
49
+ "zip_code" => "INVALID IP ADDRESS",
50
+ "time_zone" => "INVALID IP ADDRESS",
51
+ "isp" => "INVALID IP ADDRESS",
52
+ "domain" => "INVALID IP ADDRESS",
53
+ "net_speed" => "INVALID IP ADDRESS",
54
+ "idd_code" => "INVALID IP ADDRESS",
55
+ "area_code" => "INVALID IP ADDRESS",
56
+ "weather_station_code" => "INVALID IP ADDRESS",
57
+ "weather_station_name" => "INVALID IP ADDRESS",
58
+ "mcc" => "INVALID IP ADDRESS",
59
+ "mnc" => "INVALID IP ADDRESS",
60
+ "mobile_brand" => "INVALID IP ADDRESS",
61
+ "elevation" => "INVALID IP ADDRESS",
62
+ "usage_type" => "INVALID IP ADDRESS"
63
+ }
64
+ end
65
+
66
+ def query_url_params(query)
67
+ params = super
68
+ if configuration.has_key?(:package)
69
+ params.merge!(package: configuration[:package])
70
+ end
71
+ params
72
+ end
73
+
74
+ end
75
+ end