geocoder 1.6.0 → 1.6.5

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 (38) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +26 -0
  3. data/LICENSE +1 -1
  4. data/README.md +7 -30
  5. data/bin/console +13 -0
  6. data/lib/easting_northing.rb +171 -0
  7. data/lib/geocoder/configuration.rb +2 -1
  8. data/lib/geocoder/configuration_hash.rb +4 -4
  9. data/lib/geocoder/ip_address.rb +2 -1
  10. data/lib/geocoder/lookup.rb +2 -0
  11. data/lib/geocoder/lookups/ban_data_gouv_fr.rb +1 -1
  12. data/lib/geocoder/lookups/esri.rb +6 -0
  13. data/lib/geocoder/lookups/geocodio.rb +1 -1
  14. data/lib/geocoder/lookups/google.rb +7 -2
  15. data/lib/geocoder/lookups/google_places_details.rb +8 -14
  16. data/lib/geocoder/lookups/google_places_search.rb +28 -2
  17. data/lib/geocoder/lookups/google_premier.rb +4 -0
  18. data/lib/geocoder/lookups/ipgeolocation.rb +6 -18
  19. data/lib/geocoder/lookups/latlon.rb +1 -2
  20. data/lib/geocoder/lookups/maxmind_local.rb +7 -1
  21. data/lib/geocoder/lookups/nationaal_georegister_nl.rb +38 -0
  22. data/lib/geocoder/lookups/smarty_streets.rb +6 -1
  23. data/lib/geocoder/lookups/telize.rb +1 -1
  24. data/lib/geocoder/lookups/test.rb +4 -0
  25. data/lib/geocoder/lookups/uk_ordnance_survey_names.rb +59 -0
  26. data/lib/geocoder/lookups/yandex.rb +1 -2
  27. data/lib/geocoder/results/ban_data_gouv_fr.rb +26 -1
  28. data/lib/geocoder/results/db_ip_com.rb +1 -1
  29. data/lib/geocoder/results/ipregistry.rb +4 -8
  30. data/lib/geocoder/results/nationaal_georegister_nl.rb +62 -0
  31. data/lib/geocoder/results/nominatim.rb +4 -0
  32. data/lib/geocoder/results/uk_ordnance_survey_names.rb +59 -0
  33. data/lib/geocoder/results/yandex.rb +217 -59
  34. data/lib/geocoder/sql.rb +4 -4
  35. data/lib/geocoder/util.rb +29 -0
  36. data/lib/geocoder/version.rb +1 -1
  37. metadata +13 -8
  38. data/lib/hash_recursive_merge.rb +0 -73
@@ -18,16 +18,42 @@ module Geocoder
18
18
 
19
19
  private
20
20
 
21
+ def result_root_attr
22
+ 'candidates'
23
+ end
24
+
21
25
  def base_query_url(query)
22
- "#{protocol}://maps.googleapis.com/maps/api/place/textsearch/json?"
26
+ "#{protocol}://maps.googleapis.com/maps/api/place/findplacefromtext/json?"
23
27
  end
24
28
 
25
29
  def query_url_google_params(query)
26
30
  {
27
- query: query.text,
31
+ input: query.text,
32
+ inputtype: 'textquery',
33
+ fields: fields(query),
28
34
  language: query.language || configuration.language
29
35
  }
30
36
  end
37
+
38
+ def fields(query)
39
+ query_fields = query.options[:fields]
40
+ return format_fields(query_fields) if query_fields
41
+
42
+ default_fields
43
+ end
44
+
45
+ def default_fields
46
+ legacy = %w[id reference]
47
+ basic = %w[business_status formatted_address geometry icon name
48
+ photos place_id plus_code types]
49
+ contact = %w[opening_hours]
50
+ atmosphere = %W[price_level rating user_ratings_total]
51
+ format_fields(legacy, basic, contact, atmosphere)
52
+ end
53
+
54
+ def format_fields(*fields)
55
+ fields.flatten.join(',')
56
+ end
31
57
  end
32
58
  end
33
59
  end
@@ -21,6 +21,10 @@ module Geocoder::Lookup
21
21
 
22
22
  private # ---------------------------------------------------------------
23
23
 
24
+ def result_root_attr
25
+ 'results'
26
+ end
27
+
24
28
  def cache_key(query)
25
29
  "#{protocol}://maps.googleapis.com/maps/api/geocode/json?" + hash_to_query(cache_key_params(query))
26
30
  end
@@ -6,16 +6,11 @@ module Geocoder::Lookup
6
6
  class Ipgeolocation < Base
7
7
 
8
8
  ERROR_CODES = {
9
- 404 => Geocoder::InvalidRequest,
10
- 401 => Geocoder::RequestDenied, # missing/invalid API key
11
- 101 => Geocoder::InvalidApiKey,
12
- 102 => Geocoder::Error,
13
- 103 => Geocoder::InvalidRequest,
14
- 104 => Geocoder::OverQueryLimitError,
15
- 105 => Geocoder::RequestDenied,
16
- 301 => Geocoder::InvalidRequest,
17
- 302 => Geocoder::InvalidRequest,
18
- 303 => Geocoder::RequestDenied,
9
+ 400 => Geocoder::RequestDenied, # subscription is paused
10
+ 401 => Geocoder::InvalidApiKey, # missing/invalid API key
11
+ 403 => Geocoder::InvalidRequest, # invalid IP address
12
+ 404 => Geocoder::InvalidRequest, # not found
13
+ 423 => Geocoder::InvalidRequest # bogon/reserved IP address
19
14
  }
20
15
  ERROR_CODES.default = Geocoder::Error
21
16
 
@@ -42,14 +37,7 @@ module Geocoder::Lookup
42
37
  def results(query)
43
38
  # don't look up a loopback or private address, just return the stored result
44
39
  return [reserved_result(query.text)] if query.internal_ip_address?
45
- return [] unless doc = fetch_data(query)
46
- if error = doc['error']
47
- code = error['code']
48
- msg = error['info']
49
- raise_error(ERROR_CODES[code], msg ) || Geocoder.log(:warn, "Ipgeolocation Geocoding API error: #{msg}")
50
- return []
51
- end
52
- [doc]
40
+ [fetch_data(query)]
53
41
  end
54
42
 
55
43
  def reserved_result(ip)
@@ -25,8 +25,7 @@ module Geocoder::Lookup
25
25
  # The API returned a 404 response, which indicates no results found
26
26
  elsif doc['error']['type'] == 'api_error'
27
27
  []
28
- elsif
29
- doc['error']['type'] == 'authentication_error'
28
+ elsif doc['error']['type'] == 'authentication_error'
30
29
  raise_error(Geocoder::InvalidApiKey) ||
31
30
  Geocoder.log(:warn, "LatLon.io service error: invalid API key.")
32
31
  else
@@ -30,7 +30,13 @@ module Geocoder::Lookup
30
30
  def results(query)
31
31
  if configuration[:file]
32
32
  geoip_class = RUBY_PLATFORM == "java" ? JGeoIP : GeoIP
33
- result = geoip_class.new(configuration[:file]).city(query.to_s)
33
+ geoip_instance = geoip_class.new(configuration[:file])
34
+ result =
35
+ if configuration[:package] == :country
36
+ geoip_instance.country(query.to_s)
37
+ else
38
+ geoip_instance.city(query.to_s)
39
+ end
34
40
  result.nil? ? [] : [encode_hash(result.to_hash)]
35
41
  elsif configuration[:package] == :city
36
42
  addr = IPAddr.new(query.text).to_i
@@ -0,0 +1,38 @@
1
+ require 'geocoder/lookups/base'
2
+ require "geocoder/results/nationaal_georegister_nl"
3
+
4
+ module Geocoder::Lookup
5
+ class NationaalGeoregisterNl < Base
6
+
7
+ def name
8
+ 'Nationaal Georegister Nederland'
9
+ end
10
+
11
+ private # ---------------------------------------------------------------
12
+
13
+ def cache_key(query)
14
+ base_query_url(query) + hash_to_query(query_url_params(query))
15
+ end
16
+
17
+ def base_query_url(query)
18
+ "#{protocol}://geodata.nationaalgeoregister.nl/locatieserver/v3/free?"
19
+ end
20
+
21
+ def valid_response?(response)
22
+ json = parse_json(response.body)
23
+ super(response) if json
24
+ end
25
+
26
+ def results(query)
27
+ return [] unless doc = fetch_data(query)
28
+ return doc['response']['docs']
29
+ end
30
+
31
+ def query_url_params(query)
32
+ {
33
+ fl: '*',
34
+ q: query.text
35
+ }.merge(super)
36
+ end
37
+ end
38
+ end
@@ -57,7 +57,12 @@ module Geocoder::Lookup
57
57
  end
58
58
 
59
59
  def results(query)
60
- fetch_data(query) || []
60
+ doc = fetch_data(query) || []
61
+ if doc.is_a?(Hash) and doc.key?('status') # implies there's an error
62
+ return []
63
+ else
64
+ return doc
65
+ end
61
66
  end
62
67
  end
63
68
  end
@@ -16,7 +16,7 @@ module Geocoder::Lookup
16
16
  if configuration[:host]
17
17
  "#{protocol}://#{configuration[:host]}/location/#{query.sanitized_text}"
18
18
  else
19
- "#{protocol}://telize-v1.p.mashape.com/location/#{query.sanitized_text}?mashape-key=#{api_key}"
19
+ "#{protocol}://telize-v1.p.rapidapi.com/location/#{query.sanitized_text}?rapidapi-key=#{api_key}"
20
20
  end
21
21
  end
22
22
 
@@ -28,6 +28,10 @@ module Geocoder
28
28
  @stubs ||= {}
29
29
  end
30
30
 
31
+ def self.delete_stub(query_text)
32
+ stubs.delete(query_text)
33
+ end
34
+
31
35
  def self.reset
32
36
  @stubs = {}
33
37
  @default_stub = nil
@@ -0,0 +1,59 @@
1
+ require 'geocoder/lookups/base'
2
+ require 'geocoder/results/uk_ordnance_survey_names'
3
+
4
+ module Geocoder::Lookup
5
+ class UkOrdnanceSurveyNames < Base
6
+
7
+ def name
8
+ 'Ordance Survey Names'
9
+ end
10
+
11
+ def supported_protocols
12
+ [:https]
13
+ end
14
+
15
+ def base_query_url(query)
16
+ "#{protocol}://api.ordnancesurvey.co.uk/opennames/v1/find?"
17
+ end
18
+
19
+ def required_api_key_parts
20
+ ["key"]
21
+ end
22
+
23
+ def query_url(query)
24
+ base_query_url(query) + url_query_string(query)
25
+ end
26
+
27
+ private # -------------------------------------------------------------
28
+
29
+ def results(query)
30
+ return [] unless doc = fetch_data(query)
31
+ return [] if doc['header']['totalresults'].zero?
32
+ return doc['results'].map { |r| r['GAZETTEER_ENTRY'] }
33
+ end
34
+
35
+ def query_url_params(query)
36
+ {
37
+ query: query.sanitized_text,
38
+ key: configuration.api_key,
39
+ fq: filter
40
+ }.merge(super)
41
+ end
42
+
43
+ def local_types
44
+ %w[
45
+ City
46
+ Hamlet
47
+ Other_Settlement
48
+ Town
49
+ Village
50
+ Postcode
51
+ ]
52
+ end
53
+
54
+ def filter
55
+ local_types.map { |t| "local_type:#{t}" }.join(' ')
56
+ end
57
+
58
+ end
59
+ end
@@ -33,8 +33,7 @@ module Geocoder::Lookup
33
33
  return []
34
34
  end
35
35
  if doc = doc['response']['GeoObjectCollection']
36
- meta = doc['metaDataProperty']['GeocoderResponseMetaData']
37
- return meta['found'].to_i > 0 ? doc['featureMember'] : []
36
+ return doc['featureMember'].to_a
38
37
  else
39
38
  Geocoder.log(:warn, "Yandex Geocoding API error: unexpected response format.")
40
39
  return []
@@ -4,6 +4,27 @@ require 'geocoder/results/base'
4
4
  module Geocoder::Result
5
5
  class BanDataGouvFr < Base
6
6
 
7
+ STATE_CODE_MAPPINGS = {
8
+ "Guadeloupe" => "01",
9
+ "Martinique" => "02",
10
+ "Guyane" => "03",
11
+ "La Réunion" => "04",
12
+ "Mayotte" => "06",
13
+ "Île-de-France" => "11",
14
+ "Centre-Val de Loire" => "24",
15
+ "Bourgogne-Franche-Comté" => "27",
16
+ "Normandie" => "28",
17
+ "Hauts-de-France" => "32",
18
+ "Grand Est" => "44",
19
+ "Pays de la Loire" => "52",
20
+ "Bretagne" => "53",
21
+ "Nouvelle-Aquitaine" => "75",
22
+ "Occitanie" => "76",
23
+ "Auvergne-Rhône-Alpes" => "84",
24
+ "Provence-Alpes-Côte d'Azur" => "93",
25
+ "Corse" => "94"
26
+ }.freeze
27
+
7
28
  #### BASE METHODS ####
8
29
 
9
30
  def self.response_attributes
@@ -209,6 +230,10 @@ module Geocoder::Result
209
230
  end
210
231
  end
211
232
 
233
+ def region_code
234
+ STATE_CODE_MAPPINGS[region_name]
235
+ end
236
+
212
237
  def country
213
238
  "France"
214
239
  end
@@ -235,7 +260,7 @@ module Geocoder::Result
235
260
  alias_method :street, :street_name
236
261
  alias_method :city, :city_name
237
262
  alias_method :state, :region_name
238
- alias_method :state_code, :state
263
+ alias_method :state_code, :region_code
239
264
 
240
265
  #### CITIES' METHODS ####
241
266
 
@@ -16,7 +16,7 @@ module Geocoder::Result
16
16
  end
17
17
 
18
18
  def state_code
19
- @data['stateProv']
19
+ @data['stateProvCode']
20
20
  end
21
21
  alias_method :state, :state_code
22
22
 
@@ -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
@@ -0,0 +1,62 @@
1
+ require 'geocoder/results/base'
2
+
3
+ module Geocoder::Result
4
+ class NationaalGeoregisterNl < Base
5
+
6
+ def response_attributes
7
+ @data
8
+ end
9
+
10
+ def coordinates
11
+ @data['centroide_ll'][6..-2].split(' ').map(&:to_f).reverse
12
+ end
13
+
14
+ def formatted_address
15
+ @data['weergavenaam']
16
+ end
17
+
18
+ alias_method :address, :formatted_address
19
+
20
+ def province
21
+ @data['provincienaam']
22
+ end
23
+
24
+ alias_method :state, :province
25
+
26
+ def city
27
+ @data['woonplaatsnaam']
28
+ end
29
+
30
+ def district
31
+ @data['gemeentenaam']
32
+ end
33
+
34
+ def street
35
+ @data['straatnaam']
36
+ end
37
+
38
+ def street_number
39
+ @data['huis_nlt']
40
+ end
41
+
42
+ def address_components
43
+ @data
44
+ end
45
+
46
+ def state_code
47
+ @data['provinciecode']
48
+ end
49
+
50
+ def postal_code
51
+ @data['postcode']
52
+ end
53
+
54
+ def country
55
+ "Netherlands"
56
+ end
57
+
58
+ def country_code
59
+ "NL"
60
+ end
61
+ end
62
+ end
@@ -76,6 +76,10 @@ module Geocoder::Result
76
76
  @data['address']['neighbourhood']
77
77
  end
78
78
 
79
+ def municipality
80
+ @data['address']['municipality']
81
+ end
82
+
79
83
  def coordinates
80
84
  [@data['lat'].to_f, @data['lon'].to_f]
81
85
  end
@@ -0,0 +1,59 @@
1
+ require 'geocoder/results/base'
2
+ require 'easting_northing'
3
+
4
+ module Geocoder::Result
5
+ class UkOrdnanceSurveyNames < Base
6
+
7
+ def coordinates
8
+ @coordinates ||= Geocoder::EastingNorthing.new(
9
+ easting: data['GEOMETRY_X'],
10
+ northing: data['GEOMETRY_Y'],
11
+ ).lat_lng
12
+ end
13
+
14
+ def city
15
+ is_postcode? ? data['DISTRICT_BOROUGH'] : data['NAME1']
16
+ end
17
+
18
+ def county
19
+ data['COUNTY_UNITARY']
20
+ end
21
+ alias state county
22
+
23
+ def county_code
24
+ code_from_uri data['COUNTY_UNITARY_URI']
25
+ end
26
+ alias state_code county_code
27
+
28
+ def province
29
+ data['REGION']
30
+ end
31
+
32
+ def province_code
33
+ code_from_uri data['REGION_URI']
34
+ end
35
+
36
+ def postal_code
37
+ is_postcode? ? data['NAME1'] : ''
38
+ end
39
+
40
+ def country
41
+ 'United Kingdom'
42
+ end
43
+
44
+ def country_code
45
+ 'UK'
46
+ end
47
+
48
+ private
49
+
50
+ def is_postcode?
51
+ data['LOCAL_TYPE'] == 'Postcode'
52
+ end
53
+
54
+ def code_from_uri(uri)
55
+ return '' if uri.nil?
56
+ uri.split('/').last
57
+ end
58
+ end
59
+ end