geocoder 1.4.3 → 1.5.0

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 (91) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +43 -0
  3. data/README.md +364 -880
  4. data/examples/autoexpire_cache_redis.rb +3 -3
  5. data/lib/generators/geocoder/config/templates/initializer.rb +3 -2
  6. data/lib/generators/geocoder/maxmind/geolite_city_generator.rb +2 -0
  7. data/lib/generators/geocoder/maxmind/geolite_country_generator.rb +2 -0
  8. data/lib/generators/geocoder/maxmind/templates/migration/geolite_city.rb +1 -1
  9. data/lib/generators/geocoder/maxmind/templates/migration/geolite_country.rb +1 -1
  10. data/lib/generators/geocoder/migration_version.rb +15 -0
  11. data/lib/geocoder/cache.rb +6 -2
  12. data/lib/geocoder/cli.rb +2 -2
  13. data/lib/geocoder/configuration.rb +2 -2
  14. data/lib/geocoder/exceptions.rb +1 -1
  15. data/lib/geocoder/ip_address.rb +1 -1
  16. data/lib/geocoder/lookup.rb +9 -4
  17. data/lib/geocoder/lookups/amap.rb +63 -0
  18. data/lib/geocoder/lookups/baidu.rb +14 -10
  19. data/lib/geocoder/lookups/baidu_ip.rb +6 -35
  20. data/lib/geocoder/lookups/ban_data_gouv_fr.rb +4 -4
  21. data/lib/geocoder/lookups/base.rb +22 -4
  22. data/lib/geocoder/lookups/bing.rb +13 -12
  23. data/lib/geocoder/lookups/db_ip_com.rb +52 -0
  24. data/lib/geocoder/lookups/dstk.rb +4 -2
  25. data/lib/geocoder/lookups/esri.rb +1 -16
  26. data/lib/geocoder/lookups/freegeoip.rb +11 -2
  27. data/lib/geocoder/lookups/geocoder_ca.rb +4 -4
  28. data/lib/geocoder/lookups/geocoder_us.rb +17 -9
  29. data/lib/geocoder/lookups/geocodio.rb +5 -5
  30. data/lib/geocoder/lookups/geoportail_lu.rb +7 -7
  31. data/lib/geocoder/lookups/google.rb +13 -9
  32. data/lib/geocoder/lookups/google_places_details.rb +4 -4
  33. data/lib/geocoder/lookups/google_places_search.rb +4 -4
  34. data/lib/geocoder/lookups/google_premier.rb +11 -1
  35. data/lib/geocoder/lookups/here.rb +4 -4
  36. data/lib/geocoder/lookups/ip2location.rb +74 -0
  37. data/lib/geocoder/lookups/ipapi_com.rb +7 -12
  38. data/lib/geocoder/lookups/ipdata_co.rb +61 -0
  39. data/lib/geocoder/lookups/ipinfo_io.rb +10 -19
  40. data/lib/geocoder/lookups/ipstack.rb +63 -0
  41. data/lib/geocoder/lookups/latlon.rb +4 -4
  42. data/lib/geocoder/lookups/location_iq.rb +26 -8
  43. data/lib/geocoder/lookups/mapbox.rb +12 -6
  44. data/lib/geocoder/lookups/mapquest.rb +4 -5
  45. data/lib/geocoder/lookups/maxmind.rb +4 -4
  46. data/lib/geocoder/lookups/maxmind_geoip2.rb +4 -0
  47. data/lib/geocoder/lookups/nominatim.rb +17 -5
  48. data/lib/geocoder/lookups/opencagedata.rb +7 -6
  49. data/lib/geocoder/lookups/pelias.rb +6 -6
  50. data/lib/geocoder/lookups/pickpoint.rb +41 -0
  51. data/lib/geocoder/lookups/pointpin.rb +7 -6
  52. data/lib/geocoder/lookups/postcode_anywhere_uk.rb +4 -5
  53. data/lib/geocoder/lookups/postcodes_io.rb +31 -0
  54. data/lib/geocoder/lookups/smarty_streets.rb +8 -8
  55. data/lib/geocoder/lookups/telize.rb +24 -4
  56. data/lib/geocoder/lookups/yandex.rb +10 -6
  57. data/lib/geocoder/models/active_record.rb +4 -3
  58. data/lib/geocoder/request.rb +32 -0
  59. data/lib/geocoder/results/amap.rb +87 -0
  60. data/lib/geocoder/results/baidu.rb +10 -10
  61. data/lib/geocoder/results/base.rb +13 -1
  62. data/lib/geocoder/results/bing.rb +1 -1
  63. data/lib/geocoder/results/db_ip_com.rb +58 -0
  64. data/lib/geocoder/results/freegeoip.rb +0 -5
  65. data/lib/geocoder/results/geocoder_ca.rb +3 -3
  66. data/lib/geocoder/results/geoip2.rb +24 -10
  67. data/lib/geocoder/results/geoportail_lu.rb +5 -3
  68. data/lib/geocoder/results/google.rb +16 -5
  69. data/lib/geocoder/results/here.rb +8 -0
  70. data/lib/geocoder/results/ip2location.rb +22 -0
  71. data/lib/geocoder/results/ipdata_co.rb +40 -0
  72. data/lib/geocoder/results/ipstack.rb +60 -0
  73. data/lib/geocoder/results/maxmind.rb +0 -5
  74. data/lib/geocoder/results/maxmind_local.rb +0 -5
  75. data/lib/geocoder/results/nominatim.rb +12 -0
  76. data/lib/geocoder/results/opencagedata.rb +12 -2
  77. data/lib/geocoder/results/pickpoint.rb +6 -0
  78. data/lib/geocoder/results/postcodes_io.rb +40 -0
  79. data/lib/geocoder/results/smarty_streets.rb +7 -1
  80. data/lib/geocoder/results/telize.rb +0 -5
  81. data/lib/geocoder/results/test.rb +1 -1
  82. data/lib/geocoder/sql.rb +2 -2
  83. data/lib/geocoder/stores/active_record.rb +15 -4
  84. data/lib/geocoder/stores/base.rb +1 -2
  85. data/lib/geocoder/version.rb +1 -1
  86. data/lib/tasks/geocoder.rake +11 -3
  87. metadata +27 -10
  88. data/lib/geocoder/lookups/okf.rb +0 -44
  89. data/lib/geocoder/lookups/ovi.rb +0 -62
  90. data/lib/geocoder/results/okf.rb +0 -106
  91. data/lib/geocoder/results/ovi.rb +0 -71
@@ -8,11 +8,11 @@ class AutoexpireCacheRedis
8
8
  end
9
9
 
10
10
  def [](url)
11
- @store.[](url)
11
+ @store.get(url)
12
12
  end
13
13
 
14
14
  def []=(url, value)
15
- @store.[]=(url, value)
15
+ @store.set(url, value)
16
16
  @store.expire(url, @ttl)
17
17
  end
18
18
 
@@ -25,4 +25,4 @@ class AutoexpireCacheRedis
25
25
  end
26
26
  end
27
27
 
28
- Geocoder.configure(:cache => AutoexpireCacheRedis.new(Redis.new))
28
+ Geocoder.configure(:cache => AutoexpireCacheRedis.new(Redis.new))
@@ -1,13 +1,14 @@
1
1
  Geocoder.configure(
2
2
  # Geocoding options
3
3
  # timeout: 3, # geocoding service timeout (secs)
4
- # lookup: :google, # name of geocoding service (symbol)
4
+ # lookup: :nominatim, # name of geocoding service (symbol)
5
+ # ip_lookup: :ipinfo_io, # name of IP address geocoding service (symbol)
5
6
  # language: :en, # ISO-639 language code
6
7
  # use_https: false, # use HTTPS for lookup requests? (if supported)
7
8
  # http_proxy: nil, # HTTP proxy server (user:pass@host:port)
8
9
  # https_proxy: nil, # HTTPS proxy server (user:pass@host:port)
9
10
  # api_key: nil, # API key for geocoding service
10
- # cache: nil, # cache object (must respond to #[], #[]=, and #keys)
11
+ # cache: nil, # cache object (must respond to #[], #[]=, and #del)
11
12
  # cache_prefix: 'geocoder:', # prefix (string) to use for all cache keys
12
13
 
13
14
  # Exceptions that should not be rescued by default
@@ -1,10 +1,12 @@
1
1
  require 'rails/generators/migration'
2
+ require 'generators/geocoder/migration_version'
2
3
 
3
4
  module Geocoder
4
5
  module Generators
5
6
  module Maxmind
6
7
  class GeoliteCityGenerator < Rails::Generators::Base
7
8
  include Rails::Generators::Migration
9
+ include Generators::MigrationVersion
8
10
 
9
11
  source_root File.expand_path('../templates', __FILE__)
10
12
 
@@ -1,10 +1,12 @@
1
1
  require 'rails/generators/migration'
2
+ require 'generators/geocoder/migration_version'
2
3
 
3
4
  module Geocoder
4
5
  module Generators
5
6
  module Maxmind
6
7
  class GeoliteCountryGenerator < Rails::Generators::Base
7
8
  include Rails::Generators::Migration
9
+ include Generators::MigrationVersion
8
10
 
9
11
  source_root File.expand_path('../templates', __FILE__)
10
12
 
@@ -1,4 +1,4 @@
1
- class GeocoderMaxmindGeoliteCity < ActiveRecord::Migration
1
+ class GeocoderMaxmindGeoliteCity < ActiveRecord::Migration<%= migration_version %>
2
2
  def self.up
3
3
  create_table :maxmind_geolite_city_blocks, id: false do |t|
4
4
  t.column :start_ip_num, :bigint, null: false
@@ -1,4 +1,4 @@
1
- class GeocoderMaxmindGeoliteCountry < ActiveRecord::Migration
1
+ class GeocoderMaxmindGeoliteCountry < ActiveRecord::Migration<%= migration_version %>
2
2
  def self.up
3
3
  create_table :maxmind_geolite_country, id: false do |t|
4
4
  t.column :start_ip, :string
@@ -0,0 +1,15 @@
1
+ module Geocoder
2
+ module Generators
3
+ module MigrationVersion
4
+ def rails_5?
5
+ Rails::VERSION::MAJOR == 5
6
+ end
7
+
8
+ def migration_version
9
+ if rails_5?
10
+ "[#{Rails::VERSION::MAJOR}.#{Rails::VERSION::MINOR}]"
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -40,7 +40,11 @@ module Geocoder
40
40
  #
41
41
  def expire(url)
42
42
  if url == :all
43
- urls.each{ |u| expire(u) }
43
+ if store.respond_to?(:keys)
44
+ urls.each{ |u| expire(u) }
45
+ else
46
+ raise(NoMethodError, "The Geocoder cache store must implement `#keys` for `expire(:all)` to work")
47
+ end
44
48
  else
45
49
  expire_single_url(url)
46
50
  end
@@ -64,7 +68,7 @@ module Geocoder
64
68
  # that have non-nil values.
65
69
  #
66
70
  def keys
67
- store.keys.select{ |k| k.match(/^#{prefix}/) and interpret(store[k]) }
71
+ store.keys.select{ |k| k.match(/^#{prefix}/) and self[k] }
68
72
  end
69
73
 
70
74
  ##
data/lib/geocoder/cli.rb CHANGED
@@ -97,7 +97,7 @@ module Geocoder
97
97
  end
98
98
 
99
99
  if (result = Geocoder.search(query).first)
100
- google = Geocoder::Lookup.get(:google)
100
+ nominatim = Geocoder::Lookup.get(:nominatim)
101
101
  lines = [
102
102
  ["Latitude", result.latitude],
103
103
  ["Longitude", result.longitude],
@@ -106,7 +106,7 @@ module Geocoder
106
106
  ["State/province", result.state],
107
107
  ["Postal code", result.postal_code],
108
108
  ["Country", result.country],
109
- ["Google map", google.map_link_url(result.coordinates)],
109
+ ["Map", nominatim.map_link_url(result.coordinates)],
110
110
  ]
111
111
  lines.each do |line|
112
112
  out << (line[0] + ": ").ljust(18) + line[1].to_s + "\n"
@@ -97,8 +97,8 @@ module Geocoder
97
97
 
98
98
  # geocoding options
99
99
  @data[:timeout] = 3 # geocoding service timeout (secs)
100
- @data[:lookup] = :google # name of street address geocoding service (symbol)
101
- @data[:ip_lookup] = :freegeoip # name of IP address geocoding service (symbol)
100
+ @data[:lookup] = :nominatim # name of street address geocoding service (symbol)
101
+ @data[:ip_lookup] = :ipinfo_io # name of IP address geocoding service (symbol)
102
102
  @data[:language] = :en # ISO-639 language code
103
103
  @data[:http_headers] = {} # HTTP headers for lookup
104
104
  @data[:use_https] = false # use HTTPS for lookup requests? (if supported)
@@ -1,4 +1,4 @@
1
- require 'timeout' # required for Ruby 1.9.3
1
+ require 'timeout'
2
2
 
3
3
  module Geocoder
4
4
 
@@ -3,7 +3,7 @@ module Geocoder
3
3
  class IpAddress < String
4
4
 
5
5
  def loopback?
6
- valid? and (self == "0.0.0.0" or self.match(/\A127\./) or self == "::1")
6
+ valid? and !!(self == "0.0.0.0" or self.match(/\A127\./) or self == "::1")
7
7
  end
8
8
 
9
9
  def valid?
@@ -39,18 +39,19 @@ module Geocoder
39
39
  :mapquest,
40
40
  :mapzen,
41
41
  :opencagedata,
42
- :ovi,
43
42
  :pelias,
43
+ :pickpoint,
44
44
  :here,
45
45
  :baidu,
46
46
  :geocodio,
47
47
  :smarty_streets,
48
- :okf,
49
48
  :postcode_anywhere_uk,
49
+ :postcodes_io,
50
50
  :geoportail_lu,
51
51
  :ban_data_gouv_fr,
52
52
  :test,
53
- :latlon
53
+ :latlon,
54
+ :amap
54
55
  ]
55
56
  end
56
57
 
@@ -68,7 +69,11 @@ module Geocoder
68
69
  :pointpin,
69
70
  :maxmind_geoip2,
70
71
  :ipinfo_io,
71
- :ipapi_com
72
+ :ipapi_com,
73
+ :ipdata_co,
74
+ :db_ip_com,
75
+ :ipstack,
76
+ :ip2location
72
77
  ]
73
78
  end
74
79
 
@@ -0,0 +1,63 @@
1
+ require 'geocoder/lookups/base'
2
+ require "geocoder/results/amap"
3
+
4
+ module Geocoder::Lookup
5
+ class Amap < Base
6
+
7
+ def name
8
+ "AMap"
9
+ end
10
+
11
+ def required_api_key_parts
12
+ ["key"]
13
+ end
14
+
15
+ def supported_protocols
16
+ [:http]
17
+ end
18
+
19
+ private # ---------------------------------------------------------------
20
+
21
+ def base_query_url(query)
22
+ path = query.reverse_geocode? ? 'regeo' : 'geo'
23
+ "http://restapi.amap.com/v3/geocode/#{path}?"
24
+ end
25
+
26
+ def results(query, reverse = false)
27
+ return [] unless doc = fetch_data(query)
28
+ case [doc['status'], doc['info']]
29
+ when ['1', 'OK']
30
+ return doc['regeocodes'] unless doc['regeocodes'].blank?
31
+ return [doc['regeocode']] unless doc['regeocode'].blank?
32
+ return doc['geocodes'] unless doc['geocodes'].blank?
33
+ when ['0', 'INVALID_USER_KEY']
34
+ raise_error(Geocoder::InvalidApiKey, "invalid api key") ||
35
+ warn("#{self.name} Geocoding API error: invalid api key.")
36
+ else
37
+ raise_error(Geocoder::Error, "server error.") ||
38
+ warn("#{self.name} Geocoding API error: server error - [#{doc['info']}]")
39
+ end
40
+ return []
41
+ end
42
+
43
+ def query_url_params(query)
44
+ params = {
45
+ :key => configuration.api_key,
46
+ :output => "json"
47
+ }
48
+ if query.reverse_geocode?
49
+ params[:location] = revert_coordinates(query.text)
50
+ params[:extensions] = "all"
51
+ params[:coordsys] = "gps"
52
+ else
53
+ params[:address] = query.sanitized_text
54
+ end
55
+ params.merge(super)
56
+ end
57
+
58
+ def revert_coordinates(text)
59
+ [text[1],text[0]].join(",")
60
+ end
61
+
62
+ end
63
+ end
@@ -12,10 +12,6 @@ module Geocoder::Lookup
12
12
  ["key"]
13
13
  end
14
14
 
15
- def query_url(query)
16
- "#{protocol}://api.map.baidu.com/geocoder/v2/?" + url_query_string(query)
17
- end
18
-
19
15
  # HTTP only
20
16
  def supported_protocols
21
17
  [:http]
@@ -23,26 +19,34 @@ module Geocoder::Lookup
23
19
 
24
20
  private # ---------------------------------------------------------------
25
21
 
22
+ def base_query_url(query)
23
+ "#{protocol}://api.map.baidu.com/geocoder/v2/?"
24
+ end
25
+
26
+ def content_key
27
+ 'result'
28
+ end
29
+
26
30
  def results(query, reverse = false)
27
31
  return [] unless doc = fetch_data(query)
28
32
  case doc['status']
29
33
  when 0
30
- return [doc['result']] unless doc['result'].blank?
34
+ return [doc[content_key]] unless doc[content_key].blank?
31
35
  when 1, 3, 4
32
36
  raise_error(Geocoder::Error, "server error.") ||
33
- Geocoder.log(:warn, "Baidu Geocoding API error: server error.")
37
+ Geocoder.log(:warn, "#{name} Geocoding API error: server error.")
34
38
  when 2
35
39
  raise_error(Geocoder::InvalidRequest, "invalid request.") ||
36
- Geocoder.log(:warn, "Baidu Geocoding API error: invalid request.")
40
+ Geocoder.log(:warn, "#{name} Geocoding API error: invalid request.")
37
41
  when 5
38
42
  raise_error(Geocoder::InvalidApiKey, "invalid api key") ||
39
- Geocoder.log(:warn, "Baidu Geocoding API error: invalid api key.")
43
+ Geocoder.log(:warn, "#{name} Geocoding API error: invalid api key.")
40
44
  when 101, 102, 200..299
41
45
  raise_error(Geocoder::RequestDenied, "request denied") ||
42
- Geocoder.log(:warn, "Baidu Geocoding API error: request denied.")
46
+ Geocoder.log(:warn, "#{name} Geocoding API error: request denied.")
43
47
  when 300..399
44
48
  raise_error(Geocoder::OverQueryLimitError, "over query limit.") ||
45
- Geocoder.log(:warn, "Baidu Geocoding API error: over query limit.")
49
+ Geocoder.log(:warn, "#{name} Geocoding API error: over query limit.")
46
50
  end
47
51
  return []
48
52
  end
@@ -2,49 +2,20 @@ require 'geocoder/lookups/base'
2
2
  require 'geocoder/results/baidu_ip'
3
3
 
4
4
  module Geocoder::Lookup
5
- class BaiduIp < Base
5
+ class BaiduIp < Baidu
6
6
 
7
7
  def name
8
8
  "Baidu IP"
9
9
  end
10
10
 
11
- def required_api_key_parts
12
- ["key"]
13
- end
14
-
15
- def query_url(query)
16
- "#{protocol}://api.map.baidu.com/location/ip?" + url_query_string(query)
17
- end
11
+ private # ---------------------------------------------------------------
18
12
 
19
- # HTTP only
20
- def supported_protocols
21
- [:http]
13
+ def base_query_url(query)
14
+ "#{protocol}://api.map.baidu.com/location/ip?"
22
15
  end
23
16
 
24
- private # ---------------------------------------------------------------
25
-
26
- def results(query, reverse = false)
27
- return [] unless doc = fetch_data(query)
28
- case doc['status']
29
- when 0
30
- return [doc['content']] unless doc['content'].blank?
31
- when 1, 3, 4
32
- raise_error(Geocoder::Error, "server error.") ||
33
- Geocoder.log(:warn, "Baidu IP Geocoding API error: server error.")
34
- when 2
35
- raise_error(Geocoder::InvalidRequest, "invalid request.") ||
36
- Geocoder.log(:warn, "Baidu IP Geocoding API error: invalid request.")
37
- when 5
38
- raise_error(Geocoder::InvalidApiKey, "invalid api key.") ||
39
- Geocoder.log(:warn, "Baidu IP Geocoding API error: invalid api key.")
40
- when 101, 102, 200..299
41
- raise_error(Geocoder::RequestDenied, "request denied.") ||
42
- Geocoder.log(:warn, "Baidu IP Geocoding API error: request denied.")
43
- when 300..399
44
- raise_error(Geocoder::OverQueryLimitError, "over query limit") ||
45
- Geocoder.log(:warn, "Baidu IP Geocoding API error: over query limit.")
46
- end
47
- return []
17
+ def content_key
18
+ 'content'
48
19
  end
49
20
 
50
21
  def query_url_params(query)
@@ -14,13 +14,13 @@ module Geocoder::Lookup
14
14
  "https://www.openstreetmap.org/#map=19/#{coordinates.join('/')}"
15
15
  end
16
16
 
17
- def query_url(query)
17
+ private # ---------------------------------------------------------------
18
+
19
+ def base_query_url(query)
18
20
  method = query.reverse_geocode? ? "reverse" : "search"
19
- "#{protocol}://api-adresse.data.gouv.fr/#{method}/?" + url_query_string(query)
21
+ "#{protocol}://api-adresse.data.gouv.fr/#{method}/?"
20
22
  end
21
23
 
22
- private # ---------------------------------------------------------------
23
-
24
24
  def any_result?(doc)
25
25
  doc['features'].any?
26
26
  end
@@ -4,7 +4,6 @@ require 'uri'
4
4
 
5
5
  unless defined?(ActiveSupport::JSON)
6
6
  begin
7
- require 'rubygems' # for Ruby 1.8
8
7
  require 'json'
9
8
  rescue LoadError
10
9
  raise LoadError, "Please install the 'json' or 'json_pure' gem to parse geocoder results."
@@ -72,8 +71,12 @@ module Geocoder
72
71
  ##
73
72
  # URL to use for querying the geocoding engine.
74
73
  #
74
+ # Subclasses should not modify this method. Instead they should define
75
+ # base_query_url and url_query_string. If absolutely necessary to
76
+ # subclss this method, they must also subclass #cache_key.
77
+ #
75
78
  def query_url(query)
76
- fail
79
+ base_query_url(query) + url_query_string(query)
77
80
  end
78
81
 
79
82
  ##
@@ -97,6 +100,14 @@ module Geocoder
97
100
 
98
101
  private # -------------------------------------------------------------
99
102
 
103
+ ##
104
+ # String which, when concatenated with url_query_string(query)
105
+ # produces the full query URL. Should include the "?" a the end.
106
+ #
107
+ def base_query_url(query)
108
+ fail
109
+ end
110
+
100
111
  ##
101
112
  # An object with configuration data for this particular lookup.
102
113
  #
@@ -147,7 +158,14 @@ module Geocoder
147
158
  # something else (like the URL before OAuth encoding).
148
159
  #
149
160
  def cache_key(query)
150
- query_url(query)
161
+ base_query_url(query) + hash_to_query(cache_key_params(query))
162
+ end
163
+
164
+ def cache_key_params(query)
165
+ # omit api_key and token because they may vary among requests
166
+ query_url_params(query).reject do |key,value|
167
+ key.to_s.match /(key|token)/
168
+ end
151
169
  end
152
170
 
153
171
  ##
@@ -286,7 +304,7 @@ module Geocoder
286
304
  end
287
305
  rescue Timeout::Error
288
306
  raise Geocoder::LookupTimeout
289
- rescue Errno::EHOSTUNREACH, Errno::ETIMEDOUT, Errno::ENETUNREACH
307
+ rescue Errno::EHOSTUNREACH, Errno::ETIMEDOUT, Errno::ENETUNREACH, Errno::ECONNRESET
290
308
  raise Geocoder::NetworkError
291
309
  end
292
310
 
@@ -16,24 +16,20 @@ module Geocoder::Lookup
16
16
  ["key"]
17
17
  end
18
18
 
19
- def query_url(query)
20
- base_url(query) + url_query_string(query)
21
- end
22
-
23
19
  private # ---------------------------------------------------------------
24
20
 
25
- def base_url(query)
26
- url = "#{protocol}://dev.virtualearth.net/REST/v1/Locations"
27
-
28
- if !query.reverse_geocode?
21
+ def base_query_url(query)
22
+ text = CGI.escape(query.sanitized_text.strip)
23
+ url = "#{protocol}://dev.virtualearth.net/REST/v1/Locations/"
24
+ if query.reverse_geocode?
25
+ url + "#{text}?"
26
+ else
29
27
  if r = query.options[:region]
30
- url << "/#{r}"
28
+ url << "#{r}/"
31
29
  end
32
30
  # use the more forgiving 'unstructured' query format to allow special
33
31
  # chars, newlines, brackets, typos.
34
- url + "?q=" + URI.escape(query.sanitized_text.strip) + "&"
35
- else
36
- url + "/#{URI.escape(query.sanitized_text.strip)}?"
32
+ url + "?q=#{text}&"
37
33
  end
38
34
  end
39
35
 
@@ -44,6 +40,11 @@ module Geocoder::Lookup
44
40
  return doc['resourceSets'].first['estimatedTotal'] > 0 ? doc['resourceSets'].first['resources'] : []
45
41
  elsif doc['statusCode'] == 401 and doc["authenticationResultCode"] == "InvalidCredentials"
46
42
  raise_error(Geocoder::InvalidApiKey) || Geocoder.log(:warn, "Invalid Bing API key.")
43
+ elsif doc['statusCode'] == 403
44
+ raise_error(Geocoder::RequestDenied) || Geocoder.log(:warn, "Bing Geocoding API error: Forbidden Request")
45
+ elsif [500, 503].include?(doc['statusCode'])
46
+ raise_error(Geocoder::ServiceUnavailable) ||
47
+ Geocoder.log(:warn, "Bing Geocoding API error: Service Unavailable")
47
48
  else
48
49
  Geocoder.log(:warn, "Bing Geocoding API error: #{doc['statusCode']} (#{doc['statusDescription']}).")
49
50
  end
@@ -0,0 +1,52 @@
1
+ require 'geocoder/lookups/base'
2
+ require 'geocoder/results/db_ip_com'
3
+
4
+ module Geocoder::Lookup
5
+ class DbIpCom < Base
6
+
7
+ def name
8
+ 'DB-IP.com'
9
+ end
10
+
11
+ def supported_protocols
12
+ [:https, :http]
13
+ end
14
+
15
+ def required_api_key_parts
16
+ ['api_key']
17
+ end
18
+
19
+ private # ----------------------------------------------------------------
20
+
21
+ def base_query_url(query)
22
+ "#{protocol}://api.db-ip.com/v2/#{configuration.api_key}/#{query.sanitized_text}?"
23
+ end
24
+
25
+ ##
26
+ # Same as query_url but without the api key.
27
+ #
28
+ def cache_key(query)
29
+ "#{protocol}://api.db-ip.com/v2/#{query.sanitized_text}?" + hash_to_query(cache_key_params(query))
30
+ end
31
+
32
+ def results(query)
33
+ return [] unless (doc = fetch_data(query))
34
+
35
+ case doc['error']
36
+ when 'maximum number of queries per day exceeded'
37
+ raise_error Geocoder::OverQueryLimitError ||
38
+ Geocoder.log(:warn, 'DB-API query limit exceeded.')
39
+
40
+ when 'invalid API key'
41
+ raise_error Geocoder::InvalidApiKey ||
42
+ Geocoder.log(:warn, 'Invalid DB-IP API key.')
43
+ when nil
44
+ [doc]
45
+
46
+ else
47
+ raise_error Geocoder::Error ||
48
+ Geocoder.log(:warn, "Request failed: #{doc['error']}")
49
+ end
50
+ end
51
+ end
52
+ end
@@ -12,9 +12,11 @@ module Geocoder::Lookup
12
12
  "Data Science Toolkit"
13
13
  end
14
14
 
15
- def query_url(query)
15
+ private # ----------------------------------------------------------------
16
+
17
+ def base_query_url(query)
16
18
  host = configuration[:host] || "www.datasciencetoolkit.org"
17
- "#{protocol}://#{host}/maps/api/geocode/json?" + url_query_string(query)
19
+ "#{protocol}://#{host}/maps/api/geocode/json?"
18
20
  end
19
21
  end
20
22
  end
@@ -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",
@@ -9,7 +9,12 @@ module Geocoder::Lookup
9
9
  end
10
10
 
11
11
  def supported_protocols
12
- [:http]
12
+ if configuration[:host]
13
+ [:http, :https]
14
+ else
15
+ # use https for default host
16
+ [:https]
17
+ end
13
18
  end
14
19
 
15
20
  def query_url(query)
@@ -18,6 +23,10 @@ module Geocoder::Lookup
18
23
 
19
24
  private # ---------------------------------------------------------------
20
25
 
26
+ def cache_key(query)
27
+ query_url(query)
28
+ end
29
+
21
30
  def parse_raw_data(raw_data)
22
31
  raw_data.match(/^<html><title>404/) ? nil : super(raw_data)
23
32
  end
@@ -45,7 +54,7 @@ module Geocoder::Lookup
45
54
  end
46
55
 
47
56
  def host
48
- configuration[:host] || "freegeoip.io"
57
+ configuration[:host] || "freegeoip.net"
49
58
  end
50
59
  end
51
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?