geocoder 1.5.1 → 1.7.3

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 (77) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +65 -0
  3. data/LICENSE +1 -1
  4. data/README.md +333 -238
  5. data/bin/console +13 -0
  6. data/lib/easting_northing.rb +171 -0
  7. data/lib/generators/geocoder/config/templates/initializer.rb +7 -1
  8. data/lib/geocoder/cache.rb +16 -33
  9. data/lib/geocoder/cache_stores/base.rb +40 -0
  10. data/lib/geocoder/cache_stores/generic.rb +35 -0
  11. data/lib/geocoder/cache_stores/redis.rb +34 -0
  12. data/lib/geocoder/configuration.rb +11 -4
  13. data/lib/geocoder/configuration_hash.rb +4 -4
  14. data/lib/geocoder/ip_address.rb +8 -1
  15. data/lib/geocoder/lookup.rb +21 -3
  16. data/lib/geocoder/lookups/abstract_api.rb +46 -0
  17. data/lib/geocoder/lookups/amazon_location_service.rb +54 -0
  18. data/lib/geocoder/lookups/ban_data_gouv_fr.rb +14 -1
  19. data/lib/geocoder/lookups/base.rb +10 -2
  20. data/lib/geocoder/lookups/bing.rb +1 -1
  21. data/lib/geocoder/lookups/esri.rb +6 -0
  22. data/lib/geocoder/lookups/freegeoip.rb +4 -4
  23. data/lib/geocoder/lookups/geoapify.rb +72 -0
  24. data/lib/geocoder/lookups/geocodio.rb +1 -1
  25. data/lib/geocoder/lookups/geoip2.rb +4 -0
  26. data/lib/geocoder/lookups/google.rb +7 -2
  27. data/lib/geocoder/lookups/google_places_details.rb +8 -14
  28. data/lib/geocoder/lookups/google_places_search.rb +28 -2
  29. data/lib/geocoder/lookups/google_premier.rb +4 -0
  30. data/lib/geocoder/lookups/here.rb +7 -16
  31. data/lib/geocoder/lookups/ip2location.rb +10 -14
  32. data/lib/geocoder/lookups/ipdata_co.rb +1 -1
  33. data/lib/geocoder/lookups/ipgeolocation.rb +51 -0
  34. data/lib/geocoder/lookups/ipqualityscore.rb +50 -0
  35. data/lib/geocoder/lookups/ipregistry.rb +68 -0
  36. data/lib/geocoder/lookups/latlon.rb +1 -2
  37. data/lib/geocoder/lookups/maxmind_local.rb +7 -1
  38. data/lib/geocoder/lookups/melissa_street.rb +41 -0
  39. data/lib/geocoder/lookups/nationaal_georegister_nl.rb +38 -0
  40. data/lib/geocoder/lookups/osmnames.rb +57 -0
  41. data/lib/geocoder/lookups/photon.rb +89 -0
  42. data/lib/geocoder/lookups/pickpoint.rb +1 -1
  43. data/lib/geocoder/lookups/smarty_streets.rb +6 -1
  44. data/lib/geocoder/lookups/telize.rb +1 -1
  45. data/lib/geocoder/lookups/tencent.rb +9 -9
  46. data/lib/geocoder/lookups/test.rb +4 -0
  47. data/lib/geocoder/lookups/uk_ordnance_survey_names.rb +59 -0
  48. data/lib/geocoder/lookups/yandex.rb +3 -4
  49. data/lib/geocoder/results/abstract_api.rb +146 -0
  50. data/lib/geocoder/results/amazon_location_service.rb +57 -0
  51. data/lib/geocoder/results/baidu.rb +0 -4
  52. data/lib/geocoder/results/ban_data_gouv_fr.rb +27 -2
  53. data/lib/geocoder/results/db_ip_com.rb +1 -1
  54. data/lib/geocoder/results/esri.rb +5 -2
  55. data/lib/geocoder/results/geoapify.rb +179 -0
  56. data/lib/geocoder/results/here.rb +4 -1
  57. data/lib/geocoder/results/ipgeolocation.rb +59 -0
  58. data/lib/geocoder/results/ipqualityscore.rb +54 -0
  59. data/lib/geocoder/results/ipregistry.rb +304 -0
  60. data/lib/geocoder/results/mapbox.rb +10 -4
  61. data/lib/geocoder/results/melissa_street.rb +46 -0
  62. data/lib/geocoder/results/nationaal_georegister_nl.rb +62 -0
  63. data/lib/geocoder/results/nominatim.rb +27 -15
  64. data/lib/geocoder/results/osmnames.rb +56 -0
  65. data/lib/geocoder/results/photon.rb +119 -0
  66. data/lib/geocoder/results/uk_ordnance_survey_names.rb +59 -0
  67. data/lib/geocoder/results/yandex.rb +217 -59
  68. data/lib/geocoder/sql.rb +4 -4
  69. data/lib/geocoder/util.rb +29 -0
  70. data/lib/geocoder/version.rb +1 -1
  71. data/lib/maxmind_database.rb +3 -3
  72. metadata +35 -18
  73. data/examples/autoexpire_cache_dalli.rb +0 -62
  74. data/examples/autoexpire_cache_redis.rb +0 -28
  75. data/lib/geocoder/lookups/geocoder_us.rb +0 -51
  76. data/lib/geocoder/results/geocoder_us.rb +0 -39
  77. data/lib/hash_recursive_merge.rb +0 -74
data/bin/console ADDED
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'geocoder'
5
+
6
+ if File.exist?("api_keys.yml")
7
+ require 'yaml'
8
+ @api_keys = YAML.load(File.read("api_keys.yml"), symbolize_names: true)
9
+ Geocoder.configure(@api_keys)
10
+ end
11
+
12
+ require 'irb'
13
+ IRB.start
@@ -0,0 +1,171 @@
1
+ module Geocoder
2
+ class EastingNorthing
3
+ attr_reader :easting, :northing, :lat_lng
4
+
5
+ def initialize(opts)
6
+ @easting = opts[:easting]
7
+ @northing = opts[:northing]
8
+
9
+ @lat_lng = to_WGS84(to_osgb_36)
10
+ end
11
+
12
+ private
13
+
14
+ def to_osgb_36
15
+ osgb_fo = 0.9996012717
16
+ northing0 = -100_000.0
17
+ easting0 = 400_000.0
18
+ phi0 = deg_to_rad(49.0)
19
+ lambda0 = deg_to_rad(-2.0)
20
+ a = 6_377_563.396
21
+ b = 6_356_256.909
22
+ eSquared = ((a * a) - (b * b)) / (a * a)
23
+ phi = 0.0
24
+ lambda = 0.0
25
+ n = (a - b) / (a + b)
26
+ m = 0.0
27
+ phiPrime = ((northing - northing0) / (a * osgb_fo)) + phi0
28
+
29
+ while (northing - northing0 - m) >= 0.001
30
+ m =
31
+ (b * osgb_fo)\
32
+ * (((1 + n + ((5.0 / 4.0) * n * n) + ((5.0 / 4.0) * n * n * n))\
33
+ * (phiPrime - phi0))\
34
+ - (((3 * n) + (3 * n * n) + ((21.0 / 8.0) * n * n * n))\
35
+ * Math.sin(phiPrime - phi0)\
36
+ * Math.cos(phiPrime + phi0))\
37
+ + ((((15.0 / 8.0) * n * n) + ((15.0 / 8.0) * n * n * n))\
38
+ * Math.sin(2.0 * (phiPrime - phi0))\
39
+ * Math.cos(2.0 * (phiPrime + phi0)))\
40
+ - (((35.0 / 24.0) * n * n * n)\
41
+ * Math.sin(3.0 * (phiPrime - phi0))\
42
+ * Math.cos(3.0 * (phiPrime + phi0))))
43
+
44
+ phiPrime += (northing - northing0 - m) / (a * osgb_fo)
45
+ end
46
+
47
+ v = a * osgb_fo * ((1.0 - eSquared * sin_pow_2(phiPrime))**-0.5)
48
+ rho =
49
+ a\
50
+ * osgb_fo\
51
+ * (1.0 - eSquared)\
52
+ * ((1.0 - eSquared * sin_pow_2(phiPrime))**-1.5)
53
+ etaSquared = (v / rho) - 1.0
54
+ vii = Math.tan(phiPrime) / (2 * rho * v)
55
+ viii =
56
+ (Math.tan(phiPrime) / (24.0 * rho * (v**3.0)))\
57
+ * (5.0\
58
+ + (3.0 * tan_pow_2(phiPrime))\
59
+ + etaSquared\
60
+ - (9.0 * tan_pow_2(phiPrime) * etaSquared))
61
+ ix =
62
+ (Math.tan(phiPrime) / (720.0 * rho * (v**5.0)))\
63
+ * (61.0\
64
+ + (90.0 * tan_pow_2(phiPrime))\
65
+ + (45.0 * tan_pow_2(phiPrime) * tan_pow_2(phiPrime)))
66
+ x = sec(phiPrime) / v
67
+ xi =
68
+ (sec(phiPrime) / (6.0 * v * v * v))\
69
+ * ((v / rho) + (2 * tan_pow_2(phiPrime)))
70
+ xiii =
71
+ (sec(phiPrime) / (120.0 * (v**5.0)))\
72
+ * (5.0\
73
+ + (28.0 * tan_pow_2(phiPrime))\
74
+ + (24.0 * tan_pow_2(phiPrime) * tan_pow_2(phiPrime)))
75
+ xiia =
76
+ (sec(phiPrime) / (5040.0 * (v**7.0)))\
77
+ * (61.0\
78
+ + (662.0 * tan_pow_2(phiPrime))\
79
+ + (1320.0 * tan_pow_2(phiPrime) * tan_pow_2(phiPrime))\
80
+ + (720.0\
81
+ * tan_pow_2(phiPrime)\
82
+ * tan_pow_2(phiPrime)\
83
+ * tan_pow_2(phiPrime)))
84
+ phi =
85
+ phiPrime\
86
+ - (vii * ((easting - easting0)**2.0))\
87
+ + (viii * ((easting - easting0)**4.0))\
88
+ - (ix * ((easting - easting0)**6.0))
89
+ lambda =
90
+ lambda0\
91
+ + (x * (easting - easting0))\
92
+ - (xi * ((easting - easting0)**3.0))\
93
+ + (xiii * ((easting - easting0)**5.0))\
94
+ - (xiia * ((easting - easting0)**7.0))
95
+
96
+ [rad_to_deg(phi), rad_to_deg(lambda)]
97
+ end
98
+
99
+ def to_WGS84(latlng)
100
+ latitude = latlng[0]
101
+ longitude = latlng[1]
102
+
103
+ a = 6_377_563.396
104
+ b = 6_356_256.909
105
+ eSquared = ((a * a) - (b * b)) / (a * a)
106
+
107
+ phi = deg_to_rad(latitude)
108
+ lambda = deg_to_rad(longitude)
109
+ v = a / Math.sqrt(1 - eSquared * sin_pow_2(phi))
110
+ h = 0
111
+ x = (v + h) * Math.cos(phi) * Math.cos(lambda)
112
+ y = (v + h) * Math.cos(phi) * Math.sin(lambda)
113
+ z = ((1 - eSquared) * v + h) * Math.sin(phi)
114
+
115
+ tx = 446.448
116
+ ty = -124.157
117
+ tz = 542.060
118
+
119
+ s = -0.0000204894
120
+ rx = deg_to_rad(0.00004172222)
121
+ ry = deg_to_rad(0.00006861111)
122
+ rz = deg_to_rad(0.00023391666)
123
+
124
+ xB = tx + (x * (1 + s)) + (-rx * y) + (ry * z)
125
+ yB = ty + (rz * x) + (y * (1 + s)) + (-rx * z)
126
+ zB = tz + (-ry * x) + (rx * y) + (z * (1 + s))
127
+
128
+ a = 6_378_137.000
129
+ b = 6_356_752.3141
130
+ eSquared = ((a * a) - (b * b)) / (a * a)
131
+
132
+ lambdaB = rad_to_deg(Math.atan(yB / xB))
133
+ p = Math.sqrt((xB * xB) + (yB * yB))
134
+ phiN = Math.atan(zB / (p * (1 - eSquared)))
135
+
136
+ (1..10).each do |_i|
137
+ v = a / Math.sqrt(1 - eSquared * sin_pow_2(phiN))
138
+ phiN1 = Math.atan((zB + (eSquared * v * Math.sin(phiN))) / p)
139
+ phiN = phiN1
140
+ end
141
+
142
+ phiB = rad_to_deg(phiN)
143
+
144
+ [phiB, lambdaB]
145
+ end
146
+
147
+ def deg_to_rad(degrees)
148
+ degrees / 180.0 * Math::PI
149
+ end
150
+
151
+ def rad_to_deg(r)
152
+ (r / Math::PI) * 180
153
+ end
154
+
155
+ def sin_pow_2(x)
156
+ Math.sin(x) * Math.sin(x)
157
+ end
158
+
159
+ def cos_pow_2(x)
160
+ Math.cos(x) * Math.cos(x)
161
+ end
162
+
163
+ def tan_pow_2(x)
164
+ Math.tan(x) * Math.tan(x)
165
+ end
166
+
167
+ def sec(x)
168
+ 1.0 / Math.cos(x)
169
+ end
170
+ end
171
+ end
@@ -9,7 +9,7 @@ Geocoder.configure(
9
9
  # https_proxy: nil, # HTTPS proxy server (user:pass@host:port)
10
10
  # api_key: nil, # API key for geocoding service
11
11
  # cache: nil, # cache object (must respond to #[], #[]=, and #del)
12
- # cache_prefix: 'geocoder:', # prefix (string) to use for all cache keys
12
+ # cache_prefix: 'geocoder:', # DEPRECATED, please use cache_options[:prefix] instead
13
13
 
14
14
  # Exceptions that should not be rescued by default
15
15
  # (if you want to implement custom error handling);
@@ -19,4 +19,10 @@ Geocoder.configure(
19
19
  # Calculation options
20
20
  # units: :mi, # :km for kilometers or :mi for miles
21
21
  # distances: :linear # :spherical or :linear
22
+
23
+ # Cache configuration
24
+ # cache_options: {
25
+ # expiration: 2.days,
26
+ # prefix: 'geocoder:'
27
+ # }
22
28
  )
@@ -1,37 +1,29 @@
1
+ Dir["#{__dir__}/cache_stores/*.rb"].each {|file| require file }
2
+
1
3
  module Geocoder
2
4
  class Cache
3
5
 
4
- def initialize(store, prefix)
5
- @store = store
6
- @prefix = prefix
6
+ def initialize(store, config)
7
+ @class = (Object.const_get("Geocoder::CacheStore::#{store.class}") rescue Geocoder::CacheStore::Generic)
8
+ @store_service = @class.new(store, config)
7
9
  end
8
10
 
9
11
  ##
10
12
  # Read from the Cache.
11
13
  #
12
14
  def [](url)
13
- interpret case
14
- when store.respond_to?(:[])
15
- store[key_for(url)]
16
- when store.respond_to?(:get)
17
- store.get key_for(url)
18
- when store.respond_to?(:read)
19
- store.read key_for(url)
20
- end
15
+ interpret store_service.read(url)
16
+ rescue => e
17
+ warn "Geocoder cache read error: #{e}"
21
18
  end
22
19
 
23
20
  ##
24
21
  # Write to the Cache.
25
22
  #
26
23
  def []=(url, value)
27
- case
28
- when store.respond_to?(:[]=)
29
- store[key_for(url)] = value
30
- when store.respond_to?(:set)
31
- store.set key_for(url), value
32
- when store.respond_to?(:write)
33
- store.write key_for(url), value
34
- end
24
+ store_service.write(url, value)
25
+ rescue => e
26
+ warn "Geocoder cache write error: #{e}"
35
27
  end
36
28
 
37
29
  ##
@@ -40,7 +32,7 @@ module Geocoder
40
32
  #
41
33
  def expire(url)
42
34
  if url == :all
43
- if store.respond_to?(:keys)
35
+ if store_service.respond_to?(:keys)
44
36
  urls.each{ |u| expire(u) }
45
37
  else
46
38
  raise(NoMethodError, "The Geocoder cache store must implement `#keys` for `expire(:all)` to work")
@@ -53,29 +45,21 @@ module Geocoder
53
45
 
54
46
  private # ----------------------------------------------------------------
55
47
 
56
- def prefix; @prefix; end
57
- def store; @store; end
58
-
59
- ##
60
- # Cache key for a given URL.
61
- #
62
- def key_for(url)
63
- [prefix, url].join
64
- end
48
+ def store_service; @store_service; end
65
49
 
66
50
  ##
67
51
  # Array of keys with the currently configured prefix
68
52
  # that have non-nil values.
69
53
  #
70
54
  def keys
71
- store.keys.select{ |k| k.match(/^#{prefix}/) and self[k] }
55
+ store_service.keys
72
56
  end
73
57
 
74
58
  ##
75
59
  # Array of cached URLs.
76
60
  #
77
61
  def urls
78
- keys.map{ |k| k[/^#{prefix}(.*)/, 1] }
62
+ store_service.urls
79
63
  end
80
64
 
81
65
  ##
@@ -87,8 +71,7 @@ module Geocoder
87
71
  end
88
72
 
89
73
  def expire_single_url(url)
90
- key = key_for(url)
91
- store.respond_to?(:del) ? store.del(key) : store.delete(key)
74
+ store_service.remove(url)
92
75
  end
93
76
  end
94
77
  end
@@ -0,0 +1,40 @@
1
+ module Geocoder::CacheStore
2
+ class Base
3
+ def initialize(store, options)
4
+ @store = store
5
+ @config = options
6
+ @prefix = config[:prefix]
7
+ end
8
+
9
+ ##
10
+ # Array of keys with the currently configured prefix
11
+ # that have non-nil values.
12
+ def keys
13
+ store.keys.select { |k| k.match(/^#{prefix}/) and self[k] }
14
+ end
15
+
16
+ ##
17
+ # Array of cached URLs.
18
+ #
19
+ def urls
20
+ keys
21
+ end
22
+
23
+ protected # ----------------------------------------------------------------
24
+
25
+ def prefix; @prefix; end
26
+ def store; @store; end
27
+ def config; @config; end
28
+
29
+ ##
30
+ # Cache key for a given URL.
31
+ #
32
+ def key_for(url)
33
+ if url.match(/^#{prefix}/)
34
+ url
35
+ else
36
+ [prefix, url].join
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,35 @@
1
+ require 'geocoder/cache_stores/base'
2
+
3
+ module Geocoder::CacheStore
4
+ class Generic < Base
5
+ def write(url, value)
6
+ case
7
+ when store.respond_to?(:[]=)
8
+ store[key_for(url)] = value
9
+ when store.respond_to?(:set)
10
+ store.set key_for(url), value
11
+ when store.respond_to?(:write)
12
+ store.write key_for(url), value
13
+ end
14
+ end
15
+
16
+ def read(url)
17
+ case
18
+ when store.respond_to?(:[])
19
+ store[key_for(url)]
20
+ when store.respond_to?(:get)
21
+ store.get key_for(url)
22
+ when store.respond_to?(:read)
23
+ store.read key_for(url)
24
+ end
25
+ end
26
+
27
+ def keys
28
+ store.keys
29
+ end
30
+
31
+ def remove(key)
32
+ store.delete(key)
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,34 @@
1
+ require 'geocoder/cache_stores/base'
2
+
3
+ module Geocoder::CacheStore
4
+ class Redis < Base
5
+ def initialize(store, options)
6
+ super
7
+ @expiration = options[:expiration]
8
+ end
9
+
10
+ def write(url, value, expire = @expiration)
11
+ if expire.present?
12
+ store.set key_for(url), value, ex: expire
13
+ else
14
+ store.set key_for(url), value
15
+ end
16
+ end
17
+
18
+ def read(url)
19
+ store.get key_for(url)
20
+ end
21
+
22
+ def keys
23
+ store.keys("#{prefix}*")
24
+ end
25
+
26
+ def remove(key)
27
+ store.del(key)
28
+ end
29
+
30
+ private # ----------------------------------------------------------------
31
+
32
+ def expire; @expiration; end
33
+ end
34
+ end
@@ -1,5 +1,6 @@
1
1
  require 'singleton'
2
2
  require 'geocoder/configuration_hash'
3
+ require 'geocoder/util'
3
4
 
4
5
  module Geocoder
5
6
 
@@ -54,6 +55,7 @@ module Geocoder
54
55
  :lookup,
55
56
  :ip_lookup,
56
57
  :language,
58
+ :host,
57
59
  :http_headers,
58
60
  :use_https,
59
61
  :http_proxy,
@@ -66,7 +68,8 @@ module Geocoder
66
68
  :distances,
67
69
  :basic_auth,
68
70
  :logger,
69
- :kernel_logger_level
71
+ :kernel_logger_level,
72
+ :cache_options
70
73
  ]
71
74
 
72
75
  attr_accessor :data
@@ -85,7 +88,7 @@ module Geocoder
85
88
  end
86
89
 
87
90
  def configure(options)
88
- @data.rmerge!(options)
91
+ Util.recursive_hash_merge(@data, options)
89
92
  end
90
93
 
91
94
  def initialize # :nodoc
@@ -105,8 +108,8 @@ module Geocoder
105
108
  @data[:http_proxy] = nil # HTTP proxy server (user:pass@host:port)
106
109
  @data[:https_proxy] = nil # HTTPS proxy server (user:pass@host:port)
107
110
  @data[:api_key] = nil # API key for geocoding service
108
- @data[:cache] = nil # cache object (must respond to #[], #[]=, and #keys)
109
- @data[:cache_prefix] = "geocoder:" # prefix (string) to use for all cache keys
111
+ @data[:cache] = nil # cache object (must respond to #[], #[]=, and optionally #keys)
112
+ @data[:cache_prefix] = nil # - DEPRECATED - prefix (string) to use for all cache keys
110
113
  @data[:basic_auth] = {} # user and password for basic auth ({:user => "user", :password => "password"})
111
114
  @data[:logger] = :kernel # :kernel or Logger instance
112
115
  @data[:kernel_logger_level] = ::Logger::WARN # log level, if kernel logger is used
@@ -119,6 +122,10 @@ module Geocoder
119
122
  # calculation options
120
123
  @data[:units] = :mi # :mi or :km
121
124
  @data[:distances] = :linear # :linear or :spherical
125
+
126
+ # explicit cache service options
127
+ @data[:cache_options] ||= {}
128
+ @data[:cache_options][:prefix] = "geocoder:"
122
129
  end
123
130
 
124
131
  instance_eval(OPTIONS.map do |option|
@@ -1,11 +1,11 @@
1
- require 'hash_recursive_merge'
2
-
3
1
  module Geocoder
4
2
  class ConfigurationHash < Hash
5
- include HashRecursiveMerge
6
-
7
3
  def method_missing(meth, *args, &block)
8
4
  has_key?(meth) ? self[meth] : super
9
5
  end
6
+
7
+ def respond_to_missing?(meth, include_private = false)
8
+ has_key?(meth) || super
9
+ end
10
10
  end
11
11
  end
@@ -7,6 +7,12 @@ module Geocoder
7
7
  '192.168.0.0/16',
8
8
  ].map { |ip| IPAddr.new(ip) }.freeze
9
9
 
10
+ def initialize(ip)
11
+ ip = ip.to_string if ip.is_a?(IPAddr)
12
+
13
+ super(ip)
14
+ end
15
+
10
16
  def internal?
11
17
  loopback? || private?
12
18
  end
@@ -20,7 +26,8 @@ module Geocoder
20
26
  end
21
27
 
22
28
  def valid?
23
- !!((self =~ Resolv::IPv4::Regex) || (self =~ Resolv::IPv6::Regex))
29
+ ip = self[/(?<=\[)(.*?)(?=\])/] || self
30
+ !!((ip =~ Resolv::IPv4::Regex) || (ip =~ Resolv::IPv6::Regex))
24
31
  end
25
32
  end
26
33
  end
@@ -18,6 +18,14 @@ module Geocoder
18
18
  all_services - [:test]
19
19
  end
20
20
 
21
+ ##
22
+ # Array of valid Lookup service names, excluding any that do not build their own HTTP requests.
23
+ # For example, Amazon Location Service uses the AWS gem, not HTTP REST requests, to fetch data.
24
+ #
25
+ def all_services_with_http_requests
26
+ all_services_except_test - [:amazon_location_service]
27
+ end
28
+
21
29
  ##
22
30
  # All street address lookup services, default first.
23
31
  #
@@ -32,11 +40,12 @@ module Geocoder
32
40
  :google_places_search,
33
41
  :bing,
34
42
  :geocoder_ca,
35
- :geocoder_us,
36
43
  :yandex,
44
+ :nationaal_georegister_nl,
37
45
  :nominatim,
38
46
  :mapbox,
39
47
  :mapquest,
48
+ :uk_ordnance_survey_names,
40
49
  :opencagedata,
41
50
  :pelias,
42
51
  :pickpoint,
@@ -51,7 +60,12 @@ module Geocoder
51
60
  :ban_data_gouv_fr,
52
61
  :test,
53
62
  :latlon,
54
- :amap
63
+ :amap,
64
+ :osmnames,
65
+ :melissa_street,
66
+ :amazon_location_service,
67
+ :geoapify,
68
+ :photon
55
69
  ]
56
70
  end
57
71
 
@@ -61,6 +75,7 @@ module Geocoder
61
75
  def ip_services
62
76
  @ip_services ||= [
63
77
  :baidu_ip,
78
+ :abstract_api,
64
79
  :freegeoip,
65
80
  :geoip2,
66
81
  :maxmind,
@@ -69,11 +84,14 @@ module Geocoder
69
84
  :pointpin,
70
85
  :maxmind_geoip2,
71
86
  :ipinfo_io,
87
+ :ipregistry,
72
88
  :ipapi_com,
73
89
  :ipdata_co,
74
90
  :db_ip_com,
75
91
  :ipstack,
76
- :ip2location
92
+ :ip2location,
93
+ :ipgeolocation,
94
+ :ipqualityscore
77
95
  ]
78
96
  end
79
97
 
@@ -0,0 +1,46 @@
1
+ # encoding: utf-8
2
+
3
+ require 'geocoder/lookups/base'
4
+ require 'geocoder/results/abstract_api'
5
+
6
+ module Geocoder::Lookup
7
+ class AbstractApi < Base
8
+
9
+ def name
10
+ "Abstract API"
11
+ end
12
+
13
+ def required_api_key_parts
14
+ ['api_key']
15
+ end
16
+
17
+ def supported_protocols
18
+ [:https]
19
+ end
20
+
21
+ private # ---------------------------------------------------------------
22
+
23
+ def base_query_url(query)
24
+ "#{protocol}://ipgeolocation.abstractapi.com/v1/?"
25
+ end
26
+
27
+ def query_url_params(query)
28
+ params = {api_key: configuration.api_key}
29
+
30
+ ip_address = query.sanitized_text
31
+ if ip_address.is_a?(String) && ip_address.length > 0
32
+ params[:ip_address] = ip_address
33
+ end
34
+
35
+ params.merge(super)
36
+ end
37
+
38
+ def results(query, reverse = false)
39
+ if doc = fetch_data(query)
40
+ [doc]
41
+ else
42
+ []
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,54 @@
1
+ require 'geocoder/lookups/base'
2
+ require 'geocoder/results/amazon_location_service'
3
+
4
+ module Geocoder::Lookup
5
+ class AmazonLocationService < Base
6
+ def results(query)
7
+ params = query.options.dup
8
+
9
+ # index_name is required
10
+ # Aws::ParamValidator raises ArgumentError on missing required keys
11
+ params.merge!(index_name: configuration[:index_name])
12
+
13
+ # Aws::ParamValidator raises ArgumentError on unexpected keys
14
+ params.delete(:lookup)
15
+
16
+ resp = if query.reverse_geocode?
17
+ client.search_place_index_for_position(params.merge(position: query.coordinates.reverse))
18
+ else
19
+ client.search_place_index_for_text(params.merge(text: query.text))
20
+ end
21
+
22
+ resp.results.map(&:place)
23
+ end
24
+
25
+ private
26
+
27
+ def client
28
+ return @client if @client
29
+ require_sdk
30
+ keys = configuration.api_key
31
+ if keys
32
+ @client = Aws::LocationService::Client.new(
33
+ access_key_id: keys[:access_key_id],
34
+ secret_access_key: keys[:secret_access_key],
35
+ )
36
+ else
37
+ @client = Aws::LocationService::Client.new
38
+ end
39
+ end
40
+
41
+ def require_sdk
42
+ begin
43
+ require 'aws-sdk-locationservice'
44
+ rescue LoadError
45
+ raise_error(Geocoder::ConfigurationError) ||
46
+ Geocoder.log(
47
+ :error,
48
+ "Couldn't load the Amazon Location Service SDK. " +
49
+ "Install it with: gem install aws-sdk-locationservice -v '~> 1.4'"
50
+ )
51
+ end
52
+ end
53
+ end
54
+ end