geocoder 1.5.2 → 1.6.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +26 -0
  3. data/LICENSE +1 -1
  4. data/README.md +8 -10
  5. data/bin/console +13 -0
  6. data/examples/autoexpire_cache_redis.rb +2 -0
  7. data/lib/easting_northing.rb +171 -0
  8. data/lib/geocoder/configuration.rb +2 -1
  9. data/lib/geocoder/configuration_hash.rb +4 -4
  10. data/lib/geocoder/ip_address.rb +2 -1
  11. data/lib/geocoder/lookup.rb +6 -3
  12. data/lib/geocoder/lookups/ban_data_gouv_fr.rb +14 -1
  13. data/lib/geocoder/lookups/esri.rb +6 -0
  14. data/lib/geocoder/lookups/geocodio.rb +1 -1
  15. data/lib/geocoder/lookups/google.rb +7 -2
  16. data/lib/geocoder/lookups/google_places_details.rb +8 -14
  17. data/lib/geocoder/lookups/google_places_search.rb +28 -2
  18. data/lib/geocoder/lookups/google_premier.rb +4 -0
  19. data/lib/geocoder/lookups/here.rb +7 -16
  20. data/lib/geocoder/lookups/ip2location.rb +5 -13
  21. data/lib/geocoder/lookups/ipgeolocation.rb +51 -0
  22. data/lib/geocoder/lookups/latlon.rb +1 -2
  23. data/lib/geocoder/lookups/nationaal_georegister_nl.rb +38 -0
  24. data/lib/geocoder/lookups/osmnames.rb +57 -0
  25. data/lib/geocoder/lookups/pickpoint.rb +1 -1
  26. data/lib/geocoder/lookups/smarty_streets.rb +6 -1
  27. data/lib/geocoder/lookups/telize.rb +1 -1
  28. data/lib/geocoder/lookups/tencent.rb +9 -9
  29. data/lib/geocoder/lookups/uk_ordnance_survey_names.rb +59 -0
  30. data/lib/geocoder/lookups/yandex.rb +1 -2
  31. data/lib/geocoder/results/baidu.rb +0 -4
  32. data/lib/geocoder/results/ban_data_gouv_fr.rb +1 -1
  33. data/lib/geocoder/results/db_ip_com.rb +1 -1
  34. data/lib/geocoder/results/ipgeolocation.rb +59 -0
  35. data/lib/geocoder/results/nationaal_georegister_nl.rb +62 -0
  36. data/lib/geocoder/results/nominatim.rb +4 -0
  37. data/lib/geocoder/results/osmnames.rb +56 -0
  38. data/lib/geocoder/results/uk_ordnance_survey_names.rb +59 -0
  39. data/lib/geocoder/results/yandex.rb +217 -59
  40. data/lib/geocoder/sql.rb +4 -4
  41. data/lib/geocoder/util.rb +29 -0
  42. data/lib/geocoder/version.rb +1 -1
  43. data/lib/maxmind_database.rb +3 -3
  44. metadata +17 -11
  45. data/lib/geocoder/lookups/geocoder_us.rb +0 -51
  46. data/lib/geocoder/results/geocoder_us.rb +0 -39
  47. data/lib/hash_recursive_merge.rb +0 -74
@@ -22,21 +22,15 @@ module Geocoder
22
22
  "#{protocol}://maps.googleapis.com/maps/api/place/details/json?"
23
23
  end
24
24
 
25
+ def result_root_attr
26
+ 'result'
27
+ end
28
+
25
29
  def results(query)
26
- return [] unless doc = fetch_data(query)
27
-
28
- case doc["status"]
29
- when "OK"
30
- return [doc["result"]]
31
- when "OVER_QUERY_LIMIT"
32
- raise_error(Geocoder::OverQueryLimitError) || Geocoder.log(:warn, "Google Places Details API error: over query limit.")
33
- when "REQUEST_DENIED"
34
- raise_error(Geocoder::RequestDenied) || Geocoder.log(:warn, "Google Places Details API error: request denied.")
35
- when "INVALID_REQUEST"
36
- raise_error(Geocoder::InvalidRequest) || Geocoder.log(:warn, "Google Places Details API error: invalid request.")
37
- end
38
-
39
- []
30
+ result = super(query)
31
+ return [result] unless result.is_a? Array
32
+
33
+ result
40
34
  end
41
35
 
42
36
  def query_url_google_params(query)
@@ -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
@@ -9,13 +9,17 @@ module Geocoder::Lookup
9
9
  end
10
10
 
11
11
  def required_api_key_parts
12
- ["app_id", "app_code"]
12
+ ['api_key']
13
+ end
14
+
15
+ def supported_protocols
16
+ [:https]
13
17
  end
14
18
 
15
19
  private # ---------------------------------------------------------------
16
20
 
17
21
  def base_query_url(query)
18
- "#{protocol}://#{if query.reverse_geocode? then 'reverse.' end}geocoder.api.here.com/6.2/#{if query.reverse_geocode? then 'reverse' end}geocode.json?"
22
+ "#{protocol}://#{if query.reverse_geocode? then 'reverse.' end}geocoder.ls.hereapi.com/6.2/#{if query.reverse_geocode? then 'reverse' end}geocode.json?"
19
23
  end
20
24
 
21
25
  def results(query)
@@ -31,8 +35,7 @@ module Geocoder::Lookup
31
35
  def query_url_here_options(query, reverse_geocode)
32
36
  options = {
33
37
  gen: 9,
34
- app_id: api_key,
35
- app_code: api_code,
38
+ apikey: configuration.api_key,
36
39
  language: (query.language || configuration.language)
37
40
  }
38
41
  if reverse_geocode
@@ -61,17 +64,5 @@ module Geocoder::Lookup
61
64
  )
62
65
  end
63
66
  end
64
-
65
- def api_key
66
- if (a = configuration.api_key)
67
- return a.first if a.is_a?(Array)
68
- end
69
- end
70
-
71
- def api_code
72
- if (a = configuration.api_key)
73
- return a.last if a.is_a?(Array)
74
- end
75
- end
76
67
  end
77
68
  end
@@ -19,11 +19,11 @@ module Geocoder::Lookup
19
19
  end
20
20
 
21
21
  def query_url_params(query)
22
- {
23
- key: configuration.api_key ? configuration.api_key : "demo",
24
- format: "json",
25
- ip: query.sanitized_text
26
- }.merge(super)
22
+ params = super
23
+ if configuration.has_key?(:package)
24
+ params.merge!(package: configuration[:package])
25
+ end
26
+ params
27
27
  end
28
28
 
29
29
  def results(query)
@@ -63,13 +63,5 @@ module Geocoder::Lookup
63
63
  }
64
64
  end
65
65
 
66
- def query_url_params(query)
67
- params = super
68
- if configuration.has_key?(:package)
69
- params.merge!(package: configuration[:package])
70
- end
71
- params
72
- end
73
-
74
66
  end
75
67
  end
@@ -0,0 +1,51 @@
1
+ require 'geocoder/lookups/base'
2
+ require 'geocoder/results/ipgeolocation'
3
+
4
+
5
+ module Geocoder::Lookup
6
+ class Ipgeolocation < Base
7
+
8
+ ERROR_CODES = {
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
14
+ }
15
+ ERROR_CODES.default = Geocoder::Error
16
+
17
+ def name
18
+ "Ipgeolocation"
19
+ end
20
+
21
+ def supported_protocols
22
+ [:https]
23
+ end
24
+
25
+ private # ----------------------------------------------------------------
26
+
27
+ def base_query_url(query)
28
+ "#{protocol}://api.ipgeolocation.io/ipgeo?"
29
+ end
30
+ def query_url_params(query)
31
+ {
32
+ ip: query.sanitized_text,
33
+ apiKey: configuration.api_key
34
+ }.merge(super)
35
+ end
36
+
37
+ def results(query)
38
+ # don't look up a loopback or private address, just return the stored result
39
+ return [reserved_result(query.text)] if query.internal_ip_address?
40
+ [fetch_data(query)]
41
+ end
42
+
43
+ def reserved_result(ip)
44
+ {
45
+ "ip" => ip,
46
+ "country_name" => "Reserved",
47
+ "country_code2" => "RD"
48
+ }
49
+ end
50
+ end
51
+ end
@@ -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
@@ -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
@@ -0,0 +1,57 @@
1
+ require 'cgi'
2
+ require 'geocoder/lookups/base'
3
+ require 'geocoder/results/osmnames'
4
+
5
+ module Geocoder::Lookup
6
+ class Osmnames < Base
7
+
8
+ def name
9
+ 'OSM Names'
10
+ end
11
+
12
+ def required_api_key_parts
13
+ configuration[:host] ? [] : ['key']
14
+ end
15
+
16
+ def supported_protocols
17
+ [:https]
18
+ end
19
+
20
+ private
21
+
22
+ def base_query_url(query)
23
+ "#{base_url(query)}/#{params_url(query)}.js?"
24
+ end
25
+
26
+ def base_url(query)
27
+ host = configuration[:host] || 'geocoder.tilehosting.com'
28
+ "#{protocol}://#{host}"
29
+ end
30
+
31
+ def params_url(query)
32
+ method, args = 'q', CGI.escape(query.sanitized_text)
33
+ method, args = 'r', query.coordinates.join('/') if query.reverse_geocode?
34
+ "#{country_limited(query)}#{method}/#{args}"
35
+ end
36
+
37
+ def results(query)
38
+ return [] unless doc = fetch_data(query)
39
+ if (error = doc['message'])
40
+ raise_error(Geocoder::InvalidRequest, error) ||
41
+ Geocoder.log(:warn, "OSMNames Geocoding API error: #{error}")
42
+ else
43
+ return doc['results']
44
+ end
45
+ end
46
+
47
+ def query_url_params(query)
48
+ {
49
+ key: configuration.api_key
50
+ }.merge(super)
51
+ end
52
+
53
+ def country_limited(query)
54
+ "#{query.options[:country_code].downcase}/" if query.options[:country_code] && !query.reverse_geocode?
55
+ end
56
+ end
57
+ end
@@ -23,7 +23,7 @@ module Geocoder::Lookup
23
23
  end
24
24
 
25
25
  def query_url_params(query)
26
- params = {
26
+ {
27
27
  key: configuration.api_key
28
28
  }.merge(super)
29
29
  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
 
@@ -31,18 +31,18 @@ module Geocoder::Lookup
31
31
  case doc['status']
32
32
  when 0
33
33
  return [doc[content_key]]
34
- when 199
35
- raise error(Geocoder::InvalidApiKey, "invalid api key") ||
36
- Geocoder.log(:warn, "#{name} Geocoding API error: key is not enabled for web service usage.")
37
- when 311
38
- raise_error(Geocoder::RequestDenied, "request denied") ||
39
- Geocoder.log(:warn, "#{name} Geocoding API error: request denied.")
40
- when 310, 306
41
- raise_error(Geocoder::InvalidRequest, "invalid request.") ||
42
- Geocoder.log(:warn, "#{name} Geocoding API error: invalid request.")
43
34
  when 311
44
35
  raise_error(Geocoder::InvalidApiKey, "invalid api key") ||
45
36
  Geocoder.log(:warn, "#{name} Geocoding API error: invalid api key.")
37
+ when 310
38
+ raise_error(Geocoder::InvalidRequest, "invalid request.") ||
39
+ Geocoder.log(:warn, "#{name} Geocoding API error: invalid request, invalid parameters.")
40
+ when 306
41
+ raise_error(Geocoder::InvalidRequest, "invalid request.") ||
42
+ Geocoder.log(:warn, "#{name} Geocoding API error: invalid request, check response for more info.")
43
+ when 110
44
+ raise_error(Geocoder::RequestDenied, "request denied.") ||
45
+ Geocoder.log(:warn, "#{name} Geocoding API error: request source is not authorized.")
46
46
  end
47
47
  return []
48
48
  end
@@ -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