geocoder 1.6.2 → 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 (58) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +44 -0
  3. data/LICENSE +1 -1
  4. data/README.md +328 -231
  5. data/bin/console +6 -0
  6. data/lib/generators/geocoder/config/templates/initializer.rb +7 -1
  7. data/lib/geocoder/cache.rb +16 -33
  8. data/lib/geocoder/cache_stores/base.rb +40 -0
  9. data/lib/geocoder/cache_stores/generic.rb +35 -0
  10. data/lib/geocoder/cache_stores/redis.rb +34 -0
  11. data/lib/geocoder/configuration.rb +11 -4
  12. data/lib/geocoder/configuration_hash.rb +4 -4
  13. data/lib/geocoder/ip_address.rb +8 -1
  14. data/lib/geocoder/lookup.rb +16 -2
  15. data/lib/geocoder/lookups/abstract_api.rb +46 -0
  16. data/lib/geocoder/lookups/amazon_location_service.rb +54 -0
  17. data/lib/geocoder/lookups/ban_data_gouv_fr.rb +1 -1
  18. data/lib/geocoder/lookups/base.rb +8 -2
  19. data/lib/geocoder/lookups/bing.rb +1 -1
  20. data/lib/geocoder/lookups/esri.rb +6 -0
  21. data/lib/geocoder/lookups/geoapify.rb +72 -0
  22. data/lib/geocoder/lookups/geocodio.rb +1 -1
  23. data/lib/geocoder/lookups/geoip2.rb +4 -0
  24. data/lib/geocoder/lookups/google.rb +7 -2
  25. data/lib/geocoder/lookups/google_places_details.rb +8 -14
  26. data/lib/geocoder/lookups/google_places_search.rb +28 -2
  27. data/lib/geocoder/lookups/google_premier.rb +4 -0
  28. data/lib/geocoder/lookups/ip2location.rb +10 -6
  29. data/lib/geocoder/lookups/ipdata_co.rb +1 -1
  30. data/lib/geocoder/lookups/ipqualityscore.rb +50 -0
  31. data/lib/geocoder/lookups/latlon.rb +1 -2
  32. data/lib/geocoder/lookups/maxmind_local.rb +7 -1
  33. data/lib/geocoder/lookups/melissa_street.rb +41 -0
  34. data/lib/geocoder/lookups/photon.rb +89 -0
  35. data/lib/geocoder/lookups/smarty_streets.rb +6 -1
  36. data/lib/geocoder/lookups/telize.rb +1 -1
  37. data/lib/geocoder/lookups/test.rb +4 -0
  38. data/lib/geocoder/lookups/uk_ordnance_survey_names.rb +1 -1
  39. data/lib/geocoder/lookups/yandex.rb +1 -2
  40. data/lib/geocoder/results/abstract_api.rb +146 -0
  41. data/lib/geocoder/results/amazon_location_service.rb +57 -0
  42. data/lib/geocoder/results/ban_data_gouv_fr.rb +26 -1
  43. data/lib/geocoder/results/db_ip_com.rb +1 -1
  44. data/lib/geocoder/results/esri.rb +5 -2
  45. data/lib/geocoder/results/geoapify.rb +179 -0
  46. data/lib/geocoder/results/ipqualityscore.rb +54 -0
  47. data/lib/geocoder/results/ipregistry.rb +4 -8
  48. data/lib/geocoder/results/mapbox.rb +10 -4
  49. data/lib/geocoder/results/melissa_street.rb +46 -0
  50. data/lib/geocoder/results/nationaal_georegister_nl.rb +1 -1
  51. data/lib/geocoder/results/nominatim.rb +27 -15
  52. data/lib/geocoder/results/photon.rb +119 -0
  53. data/lib/geocoder/util.rb +29 -0
  54. data/lib/geocoder/version.rb +1 -1
  55. metadata +22 -10
  56. data/examples/autoexpire_cache_dalli.rb +0 -62
  57. data/examples/autoexpire_cache_redis.rb +0 -30
  58. data/lib/hash_recursive_merge.rb +0 -73
data/bin/console CHANGED
@@ -3,5 +3,11 @@
3
3
  require 'bundler/setup'
4
4
  require 'geocoder'
5
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
+
6
12
  require 'irb'
7
13
  IRB.start
@@ -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
  #
@@ -53,7 +61,11 @@ module Geocoder
53
61
  :test,
54
62
  :latlon,
55
63
  :amap,
56
- :osmnames
64
+ :osmnames,
65
+ :melissa_street,
66
+ :amazon_location_service,
67
+ :geoapify,
68
+ :photon
57
69
  ]
58
70
  end
59
71
 
@@ -63,6 +75,7 @@ module Geocoder
63
75
  def ip_services
64
76
  @ip_services ||= [
65
77
  :baidu_ip,
78
+ :abstract_api,
66
79
  :freegeoip,
67
80
  :geoip2,
68
81
  :maxmind,
@@ -77,7 +90,8 @@ module Geocoder
77
90
  :db_ip_com,
78
91
  :ipstack,
79
92
  :ip2location,
80
- :ipgeolocation
93
+ :ipgeolocation,
94
+ :ipqualityscore
81
95
  ]
82
96
  end
83
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
@@ -22,7 +22,7 @@ module Geocoder::Lookup
22
22
  end
23
23
 
24
24
  def any_result?(doc)
25
- doc['features'].any?
25
+ doc['features'] and doc['features'].any?
26
26
  end
27
27
 
28
28
  def results(query)
@@ -83,8 +83,14 @@ module Geocoder
83
83
  # The working Cache object.
84
84
  #
85
85
  def cache
86
- if @cache.nil? and store = configuration.cache
87
- @cache = Cache.new(store, configuration.cache_prefix)
86
+ if @cache.nil? && (store = configuration.cache)
87
+ cache_options = configuration.cache_options
88
+ cache_prefix = (configuration.cache_prefix rescue false)
89
+ if cache_prefix
90
+ cache_options[:prefix] ||= configuration.cache_prefix
91
+ warn '[Geocoder] cache_prefix is deprecated, please change to cache_options.prefix instead'
92
+ end
93
+ @cache = Cache.new(store, cache_options)
88
94
  end
89
95
  @cache
90
96
  end
@@ -54,7 +54,7 @@ module Geocoder::Lookup
54
54
  def query_url_params(query)
55
55
  {
56
56
  key: configuration.api_key,
57
- language: (query.language || configuration.language)
57
+ culture: (query.language || configuration.language)
58
58
  }.merge(super)
59
59
  end
60
60
 
@@ -9,6 +9,10 @@ module Geocoder::Lookup
9
9
  "Esri"
10
10
  end
11
11
 
12
+ def supported_protocols
13
+ [:https]
14
+ end
15
+
12
16
  private # ---------------------------------------------------------------
13
17
 
14
18
  def base_query_url(query)
@@ -47,6 +51,8 @@ module Geocoder::Lookup
47
51
  params[:forStorage] = for_storage_value
48
52
  end
49
53
  params[:sourceCountry] = configuration[:source_country] if configuration[:source_country]
54
+ params[:preferredLabelValues] = configuration[:preferred_label_values] if configuration[:preferred_label_values]
55
+
50
56
  params.merge(super)
51
57
  end
52
58
 
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'geocoder/lookups/base'
4
+ require 'geocoder/results/geoapify'
5
+
6
+ module Geocoder
7
+ module Lookup
8
+ # https://apidocs.geoapify.com/docs/geocoding/api
9
+ class Geoapify < Base
10
+ def name
11
+ 'Geoapify'
12
+ end
13
+
14
+ def required_api_key_parts
15
+ ['api_key']
16
+ end
17
+
18
+ def supported_protocols
19
+ [:https]
20
+ end
21
+
22
+ private
23
+
24
+ def base_query_url(query)
25
+ method = query.reverse_geocode? ? 'reverse' : 'search'
26
+ "https://api.geoapify.com/v1/geocode/#{method}?"
27
+ end
28
+
29
+ def results(query)
30
+ return [] unless (doc = fetch_data(query))
31
+
32
+ # The rest of the status codes should be already handled by the default
33
+ # functionality as the API returns correct HTTP response codes in most
34
+ # cases. There may be some unhandled cases still (such as over query
35
+ # limit reached) but there is not enough documentation to cover them.
36
+ case doc['statusCode']
37
+ when 500
38
+ raise_error(Geocoder::InvalidRequest) || Geocoder.log(:warn, doc['message'])
39
+ end
40
+
41
+ return [] unless doc['type'] == 'FeatureCollection'
42
+ return [] unless doc['features'] || doc['features'].present?
43
+
44
+ doc['features']
45
+ end
46
+
47
+ def query_url_params(query)
48
+ lang = query.language || configuration.language
49
+ params = { apiKey: configuration.api_key, lang: lang, limit: query.options[:limit] }
50
+
51
+ if query.reverse_geocode?
52
+ params.merge!(query_url_params_reverse(query))
53
+ else
54
+ params.merge!(query_url_params_coordinates(query))
55
+ end
56
+
57
+ params.merge!(super)
58
+ end
59
+
60
+ def query_url_params_coordinates(query)
61
+ { text: query.sanitized_text }
62
+ end
63
+
64
+ def query_url_params_reverse(query)
65
+ {
66
+ lat: query.coordinates[0],
67
+ lon: query.coordinates[1]
68
+ }
69
+ end
70
+ end
71
+ end
72
+ end
@@ -29,7 +29,7 @@ module Geocoder::Lookup
29
29
 
30
30
  def base_query_url(query)
31
31
  path = query.reverse_geocode? ? "reverse" : "geocode"
32
- "#{protocol}://api.geocod.io/v1.3/#{path}?"
32
+ "#{protocol}://api.geocod.io/v1.6/#{path}?"
33
33
  end
34
34
 
35
35
  def query_url_params(query)
@@ -37,6 +37,10 @@ module Geocoder
37
37
  def results(query)
38
38
  return [] unless configuration[:file]
39
39
 
40
+ if @mmdb.respond_to?(:local_ip_alias) && !configuration[:local_ip_alias].nil?
41
+ @mmdb.local_ip_alias = configuration[:local_ip_alias]
42
+ end
43
+
40
44
  result = @mmdb.lookup(query.to_s)
41
45
  result.nil? ? [] : [result]
42
46
  end
@@ -44,10 +44,15 @@ module Geocoder::Lookup
44
44
  super(response) and ['OK', 'ZERO_RESULTS'].include?(status)
45
45
  end
46
46
 
47
+ def result_root_attr
48
+ 'results'
49
+ end
50
+
47
51
  def results(query)
48
52
  return [] unless doc = fetch_data(query)
49
- case doc['status']; when "OK" # OK status implies >0 results
50
- return doc['results']
53
+ case doc['status']
54
+ when "OK" # OK status implies >0 results
55
+ return doc[result_root_attr]
51
56
  when "OVER_QUERY_LIMIT"
52
57
  raise_error(Geocoder::OverQueryLimitError) ||
53
58
  Geocoder.log(:warn, "#{name} API error: over query limit.")
@@ -22,21 +22,15 @@ module Geocoder
22
22
  "#{protocol}://maps.googleapis.com/maps/api/place/details/json?"
23
23
  end
24
24
 
25
+ def result_root_attr
26
+ 'result'
27
+ end
28
+
25
29
  def results(query)
26
- return [] unless doc = fetch_data(query)
27
-
28
- case doc["status"]
29
- when "OK"
30
- return [doc["result"]]
31
- when "OVER_QUERY_LIMIT"
32
- raise_error(Geocoder::OverQueryLimitError) || Geocoder.log(:warn, "Google Places Details API error: over query limit.")
33
- when "REQUEST_DENIED"
34
- raise_error(Geocoder::RequestDenied) || Geocoder.log(:warn, "Google Places Details API error: request denied.")
35
- when "INVALID_REQUEST"
36
- raise_error(Geocoder::InvalidRequest) || Geocoder.log(:warn, "Google Places Details API error: invalid request.")
37
- end
38
-
39
- []
30
+ result = super(query)
31
+ return [result] unless result.is_a? Array
32
+
33
+ result
40
34
  end
41
35
 
42
36
  def query_url_google_params(query)