geocoder 1.6.3 → 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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +39 -0
- data/LICENSE +1 -1
- data/README.md +328 -231
- data/lib/generators/geocoder/config/templates/initializer.rb +7 -1
- data/lib/geocoder/cache.rb +16 -33
- data/lib/geocoder/cache_stores/base.rb +40 -0
- data/lib/geocoder/cache_stores/generic.rb +35 -0
- data/lib/geocoder/cache_stores/redis.rb +34 -0
- data/lib/geocoder/configuration.rb +11 -4
- data/lib/geocoder/configuration_hash.rb +4 -4
- data/lib/geocoder/ip_address.rb +6 -0
- data/lib/geocoder/lookup.rb +16 -2
- data/lib/geocoder/lookups/abstract_api.rb +46 -0
- data/lib/geocoder/lookups/amazon_location_service.rb +54 -0
- data/lib/geocoder/lookups/ban_data_gouv_fr.rb +1 -1
- data/lib/geocoder/lookups/base.rb +8 -2
- data/lib/geocoder/lookups/bing.rb +1 -1
- data/lib/geocoder/lookups/esri.rb +4 -0
- data/lib/geocoder/lookups/geoapify.rb +72 -0
- data/lib/geocoder/lookups/geocodio.rb +1 -1
- data/lib/geocoder/lookups/geoip2.rb +4 -0
- data/lib/geocoder/lookups/google.rb +7 -2
- data/lib/geocoder/lookups/google_places_details.rb +8 -14
- data/lib/geocoder/lookups/google_places_search.rb +28 -2
- data/lib/geocoder/lookups/google_premier.rb +4 -0
- data/lib/geocoder/lookups/ip2location.rb +10 -6
- data/lib/geocoder/lookups/ipdata_co.rb +1 -1
- data/lib/geocoder/lookups/ipqualityscore.rb +50 -0
- data/lib/geocoder/lookups/maxmind_local.rb +7 -1
- data/lib/geocoder/lookups/melissa_street.rb +41 -0
- data/lib/geocoder/lookups/photon.rb +89 -0
- data/lib/geocoder/lookups/test.rb +4 -0
- data/lib/geocoder/lookups/uk_ordnance_survey_names.rb +1 -1
- data/lib/geocoder/results/abstract_api.rb +146 -0
- data/lib/geocoder/results/amazon_location_service.rb +57 -0
- data/lib/geocoder/results/ban_data_gouv_fr.rb +26 -1
- data/lib/geocoder/results/db_ip_com.rb +1 -1
- data/lib/geocoder/results/esri.rb +5 -2
- data/lib/geocoder/results/geoapify.rb +179 -0
- data/lib/geocoder/results/ipqualityscore.rb +54 -0
- data/lib/geocoder/results/ipregistry.rb +4 -8
- data/lib/geocoder/results/mapbox.rb +10 -4
- data/lib/geocoder/results/melissa_street.rb +46 -0
- data/lib/geocoder/results/nationaal_georegister_nl.rb +1 -1
- data/lib/geocoder/results/nominatim.rb +27 -15
- data/lib/geocoder/results/photon.rb +119 -0
- data/lib/geocoder/util.rb +29 -0
- data/lib/geocoder/version.rb +1 -1
- metadata +18 -5
- data/examples/autoexpire_cache_dalli.rb +0 -62
- data/examples/autoexpire_cache_redis.rb +0 -30
- data/lib/hash_recursive_merge.rb +0 -73
| @@ -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:',  #  | 
| 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 | 
             
            )
         | 
    
        data/lib/geocoder/cache.rb
    CHANGED
    
    | @@ -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,  | 
| 5 | 
            -
                  @ | 
| 6 | 
            -
                  @ | 
| 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  | 
| 14 | 
            -
             | 
| 15 | 
            -
             | 
| 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 | 
            -
                   | 
| 28 | 
            -
             | 
| 29 | 
            -
             | 
| 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  | 
| 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  | 
| 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 | 
            -
                   | 
| 55 | 
            +
                  store_service.keys
         | 
| 72 56 | 
             
                end
         | 
| 73 57 |  | 
| 74 58 | 
             
                ##
         | 
| 75 59 | 
             
                # Array of cached URLs.
         | 
| 76 60 | 
             
                #
         | 
| 77 61 | 
             
                def urls
         | 
| 78 | 
            -
                   | 
| 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 | 
            -
                   | 
| 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 | 
| 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] =  | 
| 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
         | 
    
        data/lib/geocoder/ip_address.rb
    CHANGED
    
    
    
        data/lib/geocoder/lookup.rb
    CHANGED
    
    | @@ -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
         | 
| @@ -83,8 +83,14 @@ module Geocoder | |
| 83 83 | 
             
                  # The working Cache object.
         | 
| 84 84 | 
             
                  #
         | 
| 85 85 | 
             
                  def cache
         | 
| 86 | 
            -
                    if @cache.nil?  | 
| 87 | 
            -
                       | 
| 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
         | 
| @@ -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
         | 
| @@ -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'] | 
| 50 | 
            -
             | 
| 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 | 
            -
                     | 
| 27 | 
            -
             | 
| 28 | 
            -
             | 
| 29 | 
            -
                     | 
| 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)
         |