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
| @@ -0,0 +1,179 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require 'geocoder/results/base'
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            module Geocoder
         | 
| 6 | 
            +
              module Result
         | 
| 7 | 
            +
                # https://apidocs.geoapify.com/docs/geocoding/api
         | 
| 8 | 
            +
                class Geoapify < Base
         | 
| 9 | 
            +
                  def address(_format = :full)
         | 
| 10 | 
            +
                    properties['formatted']
         | 
| 11 | 
            +
                  end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                  def address_line1
         | 
| 14 | 
            +
                    properties['address_line1']
         | 
| 15 | 
            +
                  end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                  def address_line2
         | 
| 18 | 
            +
                    properties['address_line2']
         | 
| 19 | 
            +
                  end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                  def house_number
         | 
| 22 | 
            +
                    properties['housenumber']
         | 
| 23 | 
            +
                  end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                  def street
         | 
| 26 | 
            +
                    properties['street']
         | 
| 27 | 
            +
                  end
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                  def postal_code
         | 
| 30 | 
            +
                    properties['postcode']
         | 
| 31 | 
            +
                  end
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                  def district
         | 
| 34 | 
            +
                    properties['district']
         | 
| 35 | 
            +
                  end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                  def suburb
         | 
| 38 | 
            +
                    properties['suburb']
         | 
| 39 | 
            +
                  end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                  def city
         | 
| 42 | 
            +
                    properties['city']
         | 
| 43 | 
            +
                  end
         | 
| 44 | 
            +
             | 
| 45 | 
            +
                  def county
         | 
| 46 | 
            +
                    properties['county']
         | 
| 47 | 
            +
                  end
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                  def state
         | 
| 50 | 
            +
                    properties['state']
         | 
| 51 | 
            +
                  end
         | 
| 52 | 
            +
             | 
| 53 | 
            +
                  # Not currently available in the API
         | 
| 54 | 
            +
                  def state_code
         | 
| 55 | 
            +
                    ''
         | 
| 56 | 
            +
                  end
         | 
| 57 | 
            +
             | 
| 58 | 
            +
                  def country
         | 
| 59 | 
            +
                    properties['country']
         | 
| 60 | 
            +
                  end
         | 
| 61 | 
            +
             | 
| 62 | 
            +
                  def country_code
         | 
| 63 | 
            +
                    return unless properties['country_code']
         | 
| 64 | 
            +
             | 
| 65 | 
            +
                    properties['country_code'].upcase
         | 
| 66 | 
            +
                  end
         | 
| 67 | 
            +
             | 
| 68 | 
            +
                  def coordinates
         | 
| 69 | 
            +
                    return unless properties['lat']
         | 
| 70 | 
            +
                    return unless properties['lon']
         | 
| 71 | 
            +
             | 
| 72 | 
            +
                    [properties['lat'], properties['lon']]
         | 
| 73 | 
            +
                  end
         | 
| 74 | 
            +
             | 
| 75 | 
            +
                  # See: https://tools.ietf.org/html/rfc7946#section-3.1
         | 
| 76 | 
            +
                  #
         | 
| 77 | 
            +
                  # Each feature has a "Point" type in the Geoapify API.
         | 
| 78 | 
            +
                  def geometry
         | 
| 79 | 
            +
                    return unless data['geometry']
         | 
| 80 | 
            +
             | 
| 81 | 
            +
                    symbol_hash data['geometry']
         | 
| 82 | 
            +
                  end
         | 
| 83 | 
            +
             | 
| 84 | 
            +
                  # See: https://tools.ietf.org/html/rfc7946#section-5
         | 
| 85 | 
            +
                  def bounds
         | 
| 86 | 
            +
                    data['bbox']
         | 
| 87 | 
            +
                  end
         | 
| 88 | 
            +
             | 
| 89 | 
            +
                  # Type of the result, one of:
         | 
| 90 | 
            +
                  #
         | 
| 91 | 
            +
                  #   * :unknown
         | 
| 92 | 
            +
                  #   * :amenity
         | 
| 93 | 
            +
                  #   * :building
         | 
| 94 | 
            +
                  #   * :street
         | 
| 95 | 
            +
                  #   * :suburb
         | 
| 96 | 
            +
                  #   * :district
         | 
| 97 | 
            +
                  #   * :postcode
         | 
| 98 | 
            +
                  #   * :city
         | 
| 99 | 
            +
                  #   * :county
         | 
| 100 | 
            +
                  #   * :state
         | 
| 101 | 
            +
                  #   * :country
         | 
| 102 | 
            +
                  #
         | 
| 103 | 
            +
                  def type
         | 
| 104 | 
            +
                    return :unknown unless properties['result_type']
         | 
| 105 | 
            +
             | 
| 106 | 
            +
                    properties['result_type'].to_sym
         | 
| 107 | 
            +
                  end
         | 
| 108 | 
            +
             | 
| 109 | 
            +
                  # Distance in meters to given bias:proximity or to given coordinates for
         | 
| 110 | 
            +
                  # reverse geocoding
         | 
| 111 | 
            +
                  def distance
         | 
| 112 | 
            +
                    properties['distance']
         | 
| 113 | 
            +
                  end
         | 
| 114 | 
            +
             | 
| 115 | 
            +
                  # Calculated rank for the result, containing the following keys:
         | 
| 116 | 
            +
                  #
         | 
| 117 | 
            +
                  #   * `popularity` - The popularity score of the result
         | 
| 118 | 
            +
                  #   * `confidence` - The confidence value of the result (0-1)
         | 
| 119 | 
            +
                  #   * `match_type` - The result's match type, one of following:
         | 
| 120 | 
            +
                  #      * full_match
         | 
| 121 | 
            +
                  #      * inner_part
         | 
| 122 | 
            +
                  #      * match_by_building
         | 
| 123 | 
            +
                  #      * match_by_street
         | 
| 124 | 
            +
                  #      * match_by_postcode
         | 
| 125 | 
            +
                  #      * match_by_city_or_disrict
         | 
| 126 | 
            +
                  #      * match_by_country_or_state
         | 
| 127 | 
            +
                  #
         | 
| 128 | 
            +
                  # Example:
         | 
| 129 | 
            +
                  #   {
         | 
| 130 | 
            +
                  #     popularity: 8.615793062435909,
         | 
| 131 | 
            +
                  #     confidence: 0.88,
         | 
| 132 | 
            +
                  #     match_type: :full_match
         | 
| 133 | 
            +
                  #   }
         | 
| 134 | 
            +
                  def rank
         | 
| 135 | 
            +
                    return unless properties['rank']
         | 
| 136 | 
            +
             | 
| 137 | 
            +
                    r = symbol_hash(properties['rank'])
         | 
| 138 | 
            +
                    r[:match_type] = r[:match_type].to_sym if r[:match_type]
         | 
| 139 | 
            +
                    r
         | 
| 140 | 
            +
                  end
         | 
| 141 | 
            +
             | 
| 142 | 
            +
                  # Examples:
         | 
| 143 | 
            +
                  #
         | 
| 144 | 
            +
                  # Open
         | 
| 145 | 
            +
                  #   {
         | 
| 146 | 
            +
                  #     sourcename: 'openstreetmap',
         | 
| 147 | 
            +
                  #     wheelchair: 'limited',
         | 
| 148 | 
            +
                  #     wikidata: 'Q186125',
         | 
| 149 | 
            +
                  #     wikipedia: 'en:Madison Square Garden',
         | 
| 150 | 
            +
                  #     website: 'http://www.thegarden.com/',
         | 
| 151 | 
            +
                  #     phone: '12124656741',
         | 
| 152 | 
            +
                  #     osm_type: 'W',
         | 
| 153 | 
            +
                  #     osm_id: 138141251,
         | 
| 154 | 
            +
                  #     continent: 'North America',
         | 
| 155 | 
            +
                  #   }
         | 
| 156 | 
            +
                  def datasource
         | 
| 157 | 
            +
                    return unless properties['datasource']
         | 
| 158 | 
            +
             | 
| 159 | 
            +
                    symbol_hash properties['datasource']
         | 
| 160 | 
            +
                  end
         | 
| 161 | 
            +
             | 
| 162 | 
            +
                  private
         | 
| 163 | 
            +
             | 
| 164 | 
            +
                  def properties
         | 
| 165 | 
            +
                    @properties ||= data['properties'] || {}
         | 
| 166 | 
            +
                  end
         | 
| 167 | 
            +
             | 
| 168 | 
            +
                  def symbol_hash(orig_hash)
         | 
| 169 | 
            +
                    {}.tap do |result|
         | 
| 170 | 
            +
                      orig_hash.each_key do |key|
         | 
| 171 | 
            +
                        next unless orig_hash[key]
         | 
| 172 | 
            +
             | 
| 173 | 
            +
                        result[key.to_sym] = orig_hash[key]
         | 
| 174 | 
            +
                      end
         | 
| 175 | 
            +
                    end
         | 
| 176 | 
            +
                  end
         | 
| 177 | 
            +
                end
         | 
| 178 | 
            +
              end
         | 
| 179 | 
            +
            end
         | 
| @@ -0,0 +1,54 @@ | |
| 1 | 
            +
            require 'geocoder/results/base'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Geocoder
         | 
| 4 | 
            +
              module Result
         | 
| 5 | 
            +
                class Ipqualityscore < Base
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                  def self.key_method_mappings
         | 
| 8 | 
            +
                    {
         | 
| 9 | 
            +
                      'request_id' => :request_id,
         | 
| 10 | 
            +
                      'success' => :success?,
         | 
| 11 | 
            +
                      'message' => :message,
         | 
| 12 | 
            +
                      'city' => :city,
         | 
| 13 | 
            +
                      'region' => :state,
         | 
| 14 | 
            +
                      'country_code' => :country_code,
         | 
| 15 | 
            +
                      'mobile' => :mobile?,
         | 
| 16 | 
            +
                      'fraud_score' => :fraud_score,
         | 
| 17 | 
            +
                      'ISP' => :isp,
         | 
| 18 | 
            +
                      'ASN' => :asn,
         | 
| 19 | 
            +
                      'organization' => :organization,
         | 
| 20 | 
            +
                      'is_crawler' => :crawler?,
         | 
| 21 | 
            +
                      'host' => :host,
         | 
| 22 | 
            +
                      'proxy' => :proxy?,
         | 
| 23 | 
            +
                      'vpn' => :vpn?,
         | 
| 24 | 
            +
                      'tor' => :tor?,
         | 
| 25 | 
            +
                      'active_vpn' => :active_vpn?,
         | 
| 26 | 
            +
                      'active_tor' => :active_tor?,
         | 
| 27 | 
            +
                      'recent_abuse' => :recent_abuse?,
         | 
| 28 | 
            +
                      'bot_status' => :bot?,
         | 
| 29 | 
            +
                      'connection_type' => :connection_type,
         | 
| 30 | 
            +
                      'abuse_velocity' => :abuse_velocity,
         | 
| 31 | 
            +
                      'timezone' => :timezone,
         | 
| 32 | 
            +
                    }
         | 
| 33 | 
            +
                  end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                  key_method_mappings.each_pair do |key, meth|
         | 
| 36 | 
            +
                    define_method meth do
         | 
| 37 | 
            +
                      @data[key]
         | 
| 38 | 
            +
                    end
         | 
| 39 | 
            +
                  end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                  alias_method :state_code, :state
         | 
| 42 | 
            +
                  alias_method :country, :country_code
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                  def postal_code
         | 
| 45 | 
            +
                    '' # No suitable fallback
         | 
| 46 | 
            +
                  end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                  def address
         | 
| 49 | 
            +
                    [city, state, country_code].compact.reject(&:empty?).join(', ')
         | 
| 50 | 
            +
                  end
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                end
         | 
| 53 | 
            +
              end
         | 
| 54 | 
            +
            end
         | 
| @@ -9,6 +9,10 @@ module Geocoder::Result | |
| 9 9 | 
             
                  @data = flatten_hash(data)
         | 
| 10 10 | 
             
                end
         | 
| 11 11 |  | 
| 12 | 
            +
                def coordinates
         | 
| 13 | 
            +
                  [@data['location_latitude'], @data['location_longitude']]
         | 
| 14 | 
            +
                end
         | 
| 15 | 
            +
             | 
| 12 16 | 
             
                def flatten_hash(hash)
         | 
| 13 17 | 
             
                  hash.each_with_object({}) do |(k, v), h|
         | 
| 14 18 | 
             
                    if v.is_a? Hash
         | 
| @@ -35,14 +39,6 @@ module Geocoder::Result | |
| 35 39 | 
             
                  @data['location_country_code']
         | 
| 36 40 | 
             
                end
         | 
| 37 41 |  | 
| 38 | 
            -
                def latitude
         | 
| 39 | 
            -
                  @data['location_latitude']
         | 
| 40 | 
            -
                end
         | 
| 41 | 
            -
             | 
| 42 | 
            -
                def longitude
         | 
| 43 | 
            -
                  @data['location_longitude']
         | 
| 44 | 
            -
                end
         | 
| 45 | 
            -
             | 
| 46 42 | 
             
                def postal_code
         | 
| 47 43 | 
             
                  @data['location_postal']
         | 
| 48 44 | 
             
                end
         | 
| @@ -23,7 +23,10 @@ module Geocoder::Result | |
| 23 23 | 
             
                  context_part('region')
         | 
| 24 24 | 
             
                end
         | 
| 25 25 |  | 
| 26 | 
            -
                 | 
| 26 | 
            +
                def state_code
         | 
| 27 | 
            +
                  value = context_part('region', 'short_code')
         | 
| 28 | 
            +
                  value.split('-').last unless value.nil?
         | 
| 29 | 
            +
                end
         | 
| 27 30 |  | 
| 28 31 | 
             
                def postal_code
         | 
| 29 32 | 
             
                  context_part('postcode')
         | 
| @@ -33,7 +36,10 @@ module Geocoder::Result | |
| 33 36 | 
             
                  context_part('country')
         | 
| 34 37 | 
             
                end
         | 
| 35 38 |  | 
| 36 | 
            -
                 | 
| 39 | 
            +
                def country_code
         | 
| 40 | 
            +
                  value = context_part('country', 'short_code')
         | 
| 41 | 
            +
                  value.upcase unless value.nil?
         | 
| 42 | 
            +
                end
         | 
| 37 43 |  | 
| 38 44 | 
             
                def neighborhood
         | 
| 39 45 | 
             
                  context_part('neighborhood')
         | 
| @@ -45,8 +51,8 @@ module Geocoder::Result | |
| 45 51 |  | 
| 46 52 | 
             
                private
         | 
| 47 53 |  | 
| 48 | 
            -
                def context_part(name)
         | 
| 49 | 
            -
                  context. | 
| 54 | 
            +
                def context_part(name, key = 'text')
         | 
| 55 | 
            +
                  (context.detect { |c| c['id'] =~ Regexp.new(name) } || {})[key]
         | 
| 50 56 | 
             
                end
         | 
| 51 57 |  | 
| 52 58 | 
             
                def context
         | 
| @@ -0,0 +1,46 @@ | |
| 1 | 
            +
            require 'geocoder/results/base'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Geocoder::Result
         | 
| 4 | 
            +
              class MelissaStreet < Base
         | 
| 5 | 
            +
                def address(format = :full)
         | 
| 6 | 
            +
                  @data['FormattedAddress']
         | 
| 7 | 
            +
                end
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                def street_address
         | 
| 10 | 
            +
                  @data['AddressLine1']
         | 
| 11 | 
            +
                end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                def suffix
         | 
| 14 | 
            +
                  @data['ThoroughfareTrailingType']
         | 
| 15 | 
            +
                end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                def number
         | 
| 18 | 
            +
                  @data['PremisesNumber']
         | 
| 19 | 
            +
                end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                def city
         | 
| 22 | 
            +
                  @data['Locality']
         | 
| 23 | 
            +
                end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                def state_code
         | 
| 26 | 
            +
                  @data['AdministrativeArea']
         | 
| 27 | 
            +
                end
         | 
| 28 | 
            +
                alias_method :state, :state_code
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                def country
         | 
| 31 | 
            +
                  @data['CountryName']
         | 
| 32 | 
            +
                end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                def country_code
         | 
| 35 | 
            +
                  @data['CountryISO3166_1_Alpha2']
         | 
| 36 | 
            +
                end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                def postal_code
         | 
| 39 | 
            +
                  @data['PostalCode']
         | 
| 40 | 
            +
                end
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                def coordinates
         | 
| 43 | 
            +
                  [@data['Latitude'].to_f, @data['Longitude'].to_f]
         | 
| 44 | 
            +
                end
         | 
| 45 | 
            +
              end
         | 
| 46 | 
            +
            end
         | 
| @@ -4,12 +4,12 @@ module Geocoder::Result | |
| 4 4 | 
             
              class Nominatim < Base
         | 
| 5 5 |  | 
| 6 6 | 
             
                def poi
         | 
| 7 | 
            -
                  return  | 
| 7 | 
            +
                  return address_data[place_type] if address_data.key?(place_type)
         | 
| 8 8 | 
             
                  return nil
         | 
| 9 9 | 
             
                end
         | 
| 10 10 |  | 
| 11 11 | 
             
                def house_number
         | 
| 12 | 
            -
                   | 
| 12 | 
            +
                  address_data['house_number']
         | 
| 13 13 | 
             
                end
         | 
| 14 14 |  | 
| 15 15 | 
             
                def address
         | 
| @@ -18,65 +18,71 @@ module Geocoder::Result | |
| 18 18 |  | 
| 19 19 | 
             
                def street
         | 
| 20 20 | 
             
                  %w[road pedestrian highway].each do |key|
         | 
| 21 | 
            -
                    return  | 
| 21 | 
            +
                    return address_data[key] if address_data.key?(key)
         | 
| 22 22 | 
             
                  end
         | 
| 23 23 | 
             
                  return nil
         | 
| 24 24 | 
             
                end
         | 
| 25 25 |  | 
| 26 26 | 
             
                def city
         | 
| 27 27 | 
             
                  %w[city town village hamlet].each do |key|
         | 
| 28 | 
            -
                    return  | 
| 28 | 
            +
                    return address_data[key] if address_data.key?(key)
         | 
| 29 29 | 
             
                  end
         | 
| 30 30 | 
             
                  return nil
         | 
| 31 31 | 
             
                end
         | 
| 32 32 |  | 
| 33 33 | 
             
                def village
         | 
| 34 | 
            -
                   | 
| 34 | 
            +
                  address_data['village']
         | 
| 35 35 | 
             
                end
         | 
| 36 36 |  | 
| 37 37 | 
             
                def town
         | 
| 38 | 
            -
                   | 
| 38 | 
            +
                  address_data['town']
         | 
| 39 39 | 
             
                end
         | 
| 40 40 |  | 
| 41 41 | 
             
                def state
         | 
| 42 | 
            -
                   | 
| 42 | 
            +
                  address_data['state']
         | 
| 43 43 | 
             
                end
         | 
| 44 44 |  | 
| 45 45 | 
             
                alias_method :state_code, :state
         | 
| 46 46 |  | 
| 47 47 | 
             
                def postal_code
         | 
| 48 | 
            -
                   | 
| 48 | 
            +
                  address_data['postcode']
         | 
| 49 49 | 
             
                end
         | 
| 50 50 |  | 
| 51 51 | 
             
                def county
         | 
| 52 | 
            -
                   | 
| 52 | 
            +
                  address_data['county']
         | 
| 53 53 | 
             
                end
         | 
| 54 54 |  | 
| 55 55 | 
             
                def country
         | 
| 56 | 
            -
                   | 
| 56 | 
            +
                  address_data['country']
         | 
| 57 57 | 
             
                end
         | 
| 58 58 |  | 
| 59 59 | 
             
                def country_code
         | 
| 60 | 
            -
                   | 
| 60 | 
            +
                  address_data['country_code']
         | 
| 61 61 | 
             
                end
         | 
| 62 62 |  | 
| 63 63 | 
             
                def suburb
         | 
| 64 | 
            -
                   | 
| 64 | 
            +
                  address_data['suburb']
         | 
| 65 65 | 
             
                end
         | 
| 66 66 |  | 
| 67 67 | 
             
                def city_district
         | 
| 68 | 
            -
                   | 
| 68 | 
            +
                  address_data['city_district']
         | 
| 69 69 | 
             
                end
         | 
| 70 70 |  | 
| 71 71 | 
             
                def state_district
         | 
| 72 | 
            -
                   | 
| 72 | 
            +
                  address_data['state_district']
         | 
| 73 73 | 
             
                end
         | 
| 74 74 |  | 
| 75 75 | 
             
                def neighbourhood
         | 
| 76 | 
            -
                   | 
| 76 | 
            +
                  address_data['neighbourhood']
         | 
| 77 | 
            +
                end
         | 
| 78 | 
            +
             | 
| 79 | 
            +
                def municipality
         | 
| 80 | 
            +
                  address_data['municipality']
         | 
| 77 81 | 
             
                end
         | 
| 78 82 |  | 
| 79 83 | 
             
                def coordinates
         | 
| 84 | 
            +
                  return [] unless @data['lat'] && @data['lon']
         | 
| 85 | 
            +
             | 
| 80 86 | 
             
                  [@data['lat'].to_f, @data['lon'].to_f]
         | 
| 81 87 | 
             
                end
         | 
| 82 88 |  | 
| @@ -105,5 +111,11 @@ module Geocoder::Result | |
| 105 111 | 
             
                    end
         | 
| 106 112 | 
             
                  end
         | 
| 107 113 | 
             
                end
         | 
| 114 | 
            +
             | 
| 115 | 
            +
                private
         | 
| 116 | 
            +
             | 
| 117 | 
            +
                def address_data
         | 
| 118 | 
            +
                  @data['address'] || {}
         | 
| 119 | 
            +
                end
         | 
| 108 120 | 
             
              end
         | 
| 109 121 | 
             
            end
         | 
| @@ -0,0 +1,119 @@ | |
| 1 | 
            +
            require 'geocoder/results/base'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Geocoder::Result
         | 
| 4 | 
            +
              class Photon < Base
         | 
| 5 | 
            +
                def name
         | 
| 6 | 
            +
                  properties['name']
         | 
| 7 | 
            +
                end
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                def address(_format = :full)
         | 
| 10 | 
            +
                  parts = []
         | 
| 11 | 
            +
                  parts << name if name
         | 
| 12 | 
            +
                  parts << street_address if street_address
         | 
| 13 | 
            +
                  parts << city
         | 
| 14 | 
            +
                  parts << state if state
         | 
| 15 | 
            +
                  parts << postal_code
         | 
| 16 | 
            +
                  parts << country
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                  parts.join(', ')
         | 
| 19 | 
            +
                end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                def street_address
         | 
| 22 | 
            +
                  return unless street
         | 
| 23 | 
            +
                  return street unless house_number
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                  "#{house_number} #{street}"
         | 
| 26 | 
            +
                end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                def house_number
         | 
| 29 | 
            +
                  properties['housenumber']
         | 
| 30 | 
            +
                end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                def street
         | 
| 33 | 
            +
                  properties['street']
         | 
| 34 | 
            +
                end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                def postal_code
         | 
| 37 | 
            +
                  properties['postcode']
         | 
| 38 | 
            +
                end
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                def city
         | 
| 41 | 
            +
                  properties['city']
         | 
| 42 | 
            +
                end
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                def state
         | 
| 45 | 
            +
                  properties['state']
         | 
| 46 | 
            +
                end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                def state_code
         | 
| 49 | 
            +
                  ''
         | 
| 50 | 
            +
                end
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                def country
         | 
| 53 | 
            +
                  properties['country']
         | 
| 54 | 
            +
                end
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                def country_code
         | 
| 57 | 
            +
                  ''
         | 
| 58 | 
            +
                end
         | 
| 59 | 
            +
             | 
| 60 | 
            +
                def coordinates
         | 
| 61 | 
            +
                  return unless geometry
         | 
| 62 | 
            +
                  return unless geometry[:coordinates]
         | 
| 63 | 
            +
             | 
| 64 | 
            +
                  geometry[:coordinates].reverse
         | 
| 65 | 
            +
                end
         | 
| 66 | 
            +
             | 
| 67 | 
            +
                def geometry
         | 
| 68 | 
            +
                  return unless data['geometry']
         | 
| 69 | 
            +
             | 
| 70 | 
            +
                  symbol_hash data['geometry']
         | 
| 71 | 
            +
                end
         | 
| 72 | 
            +
             | 
| 73 | 
            +
                def bounds
         | 
| 74 | 
            +
                  properties['extent']
         | 
| 75 | 
            +
                end
         | 
| 76 | 
            +
             | 
| 77 | 
            +
                # Type of the result (OSM object type), one of:
         | 
| 78 | 
            +
                #
         | 
| 79 | 
            +
                #   :node
         | 
| 80 | 
            +
                #   :way
         | 
| 81 | 
            +
                #   :relation
         | 
| 82 | 
            +
                #
         | 
| 83 | 
            +
                def type
         | 
| 84 | 
            +
                  {
         | 
| 85 | 
            +
                    'N' => :node,
         | 
| 86 | 
            +
                    'W' => :way,
         | 
| 87 | 
            +
                    'R' => :relation
         | 
| 88 | 
            +
                  }[properties['osm_type']]
         | 
| 89 | 
            +
                end
         | 
| 90 | 
            +
             | 
| 91 | 
            +
                def osm_id
         | 
| 92 | 
            +
                  properties['osm_id']
         | 
| 93 | 
            +
                end
         | 
| 94 | 
            +
             | 
| 95 | 
            +
                # See: https://wiki.openstreetmap.org/wiki/Tags
         | 
| 96 | 
            +
                def osm_tag
         | 
| 97 | 
            +
                  return unless properties['osm_key']
         | 
| 98 | 
            +
                  return properties['osm_key'] unless properties['osm_value']
         | 
| 99 | 
            +
             | 
| 100 | 
            +
                  "#{properties['osm_key']}=#{properties['osm_value']}"
         | 
| 101 | 
            +
                end
         | 
| 102 | 
            +
             | 
| 103 | 
            +
                private
         | 
| 104 | 
            +
             | 
| 105 | 
            +
                def properties
         | 
| 106 | 
            +
                  @properties ||= data['properties'] || {}
         | 
| 107 | 
            +
                end
         | 
| 108 | 
            +
             | 
| 109 | 
            +
                def symbol_hash(orig_hash)
         | 
| 110 | 
            +
                  {}.tap do |result|
         | 
| 111 | 
            +
                    orig_hash.each_key do |key|
         | 
| 112 | 
            +
                      next unless orig_hash[key]
         | 
| 113 | 
            +
             | 
| 114 | 
            +
                      result[key.to_sym] = orig_hash[key]
         | 
| 115 | 
            +
                    end
         | 
| 116 | 
            +
                  end
         | 
| 117 | 
            +
                end
         | 
| 118 | 
            +
              end
         | 
| 119 | 
            +
            end
         | 
| @@ -0,0 +1,29 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Geocoder
         | 
| 4 | 
            +
              module Util
         | 
| 5 | 
            +
                #
         | 
| 6 | 
            +
                # Recursive version of Hash#merge!
         | 
| 7 | 
            +
                #
         | 
| 8 | 
            +
                # Adds the contents of +h2+ to +h1+,
         | 
| 9 | 
            +
                # merging entries in +h1+ with duplicate keys with those from +h2+.
         | 
| 10 | 
            +
                #
         | 
| 11 | 
            +
                # Compared with Hash#merge!, this method supports nested hashes.
         | 
| 12 | 
            +
                # When both +h1+ and +h2+ contains an entry with the same key,
         | 
| 13 | 
            +
                # it merges and returns the values from both hashes.
         | 
| 14 | 
            +
                #
         | 
| 15 | 
            +
                #    h1 = {"a" => 100, "b" => 200, "c" => {"c1" => 12, "c2" => 14}}
         | 
| 16 | 
            +
                #    h2 = {"b" => 254, "c" => {"c1" => 16, "c3" => 94}}
         | 
| 17 | 
            +
                #    recursive_hash_merge(h1, h2)   #=> {"a" => 100, "b" => 254, "c" => {"c1" => 16, "c2" => 14, "c3" => 94}}
         | 
| 18 | 
            +
                #
         | 
| 19 | 
            +
                # Simply using Hash#merge! would return
         | 
| 20 | 
            +
                #
         | 
| 21 | 
            +
                #    h1.merge!(h2)    #=> {"a" => 100, "b" = >254, "c" => {"c1" => 16, "c3" => 94}}
         | 
| 22 | 
            +
                #
         | 
| 23 | 
            +
                def self.recursive_hash_merge(h1, h2)
         | 
| 24 | 
            +
                  h1.merge!(h2) do |_key, oldval, newval|
         | 
| 25 | 
            +
                    oldval.class == h1.class ? self.recursive_hash_merge(oldval, newval) : newval
         | 
| 26 | 
            +
                  end
         | 
| 27 | 
            +
                end
         | 
| 28 | 
            +
              end
         | 
| 29 | 
            +
            end
         | 
    
        data/lib/geocoder/version.rb
    CHANGED