geocoder 1.6.6 → 1.8.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +68 -2
- data/README.md +355 -211
- data/examples/app_defined_lookup_services.rb +22 -0
- data/lib/generators/geocoder/config/templates/initializer.rb +6 -1
- data/lib/geocoder/cache.rb +14 -35
- 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 +17 -4
- data/lib/geocoder/ip_address.rb +9 -0
- data/lib/geocoder/lookup.rb +37 -5
- data/lib/geocoder/lookups/abstract_api.rb +46 -0
- data/lib/geocoder/lookups/amap.rb +2 -2
- data/lib/geocoder/lookups/amazon_location_service.rb +58 -0
- data/lib/geocoder/lookups/azure.rb +56 -0
- data/lib/geocoder/lookups/ban_data_gouv_fr.rb +1 -1
- data/lib/geocoder/lookups/base.rb +2 -1
- data/lib/geocoder/lookups/bing.rb +2 -2
- data/lib/geocoder/lookups/esri.rb +18 -5
- data/lib/geocoder/lookups/freegeoip.rb +8 -6
- data/lib/geocoder/lookups/geoapify.rb +78 -0
- data/lib/geocoder/lookups/geoip2.rb +4 -0
- data/lib/geocoder/lookups/geoportail_lu.rb +1 -1
- data/lib/geocoder/lookups/google_places_details.rb +20 -0
- data/lib/geocoder/lookups/google_places_search.rb +21 -5
- data/lib/geocoder/lookups/here.rb +25 -20
- data/lib/geocoder/lookups/ip2location.rb +10 -6
- data/lib/geocoder/lookups/ip2location_io.rb +62 -0
- data/lib/geocoder/lookups/ip2location_lite.rb +40 -0
- data/lib/geocoder/lookups/ipbase.rb +49 -0
- data/lib/geocoder/lookups/ipdata_co.rb +1 -1
- data/lib/geocoder/lookups/ipqualityscore.rb +50 -0
- data/lib/geocoder/lookups/location_iq.rb +5 -1
- data/lib/geocoder/lookups/mapbox.rb +3 -3
- data/lib/geocoder/lookups/melissa_street.rb +41 -0
- data/lib/geocoder/lookups/pc_miler.rb +85 -0
- data/lib/geocoder/lookups/pdok_nl.rb +43 -0
- data/lib/geocoder/lookups/photon.rb +89 -0
- data/lib/geocoder/lookups/test.rb +1 -0
- data/lib/geocoder/lookups/twogis.rb +58 -0
- data/lib/geocoder/lookups/uk_ordnance_survey_names.rb +1 -1
- data/lib/geocoder/lookups/yandex.rb +3 -3
- data/lib/geocoder/query.rb +1 -1
- data/lib/geocoder/results/abstract_api.rb +146 -0
- data/lib/geocoder/results/amazon_location_service.rb +62 -0
- data/lib/geocoder/results/azure.rb +65 -0
- data/lib/geocoder/results/ban_data_gouv_fr.rb +1 -1
- data/lib/geocoder/results/esri.rb +5 -2
- data/lib/geocoder/results/geoapify.rb +179 -0
- data/lib/geocoder/results/here.rb +20 -25
- data/lib/geocoder/results/ip2location_io.rb +21 -0
- data/lib/geocoder/results/ip2location_lite.rb +47 -0
- data/lib/geocoder/results/ipbase.rb +40 -0
- data/lib/geocoder/results/ipqualityscore.rb +54 -0
- data/lib/geocoder/results/mapbox.rb +34 -10
- data/lib/geocoder/results/melissa_street.rb +46 -0
- data/lib/geocoder/results/nominatim.rb +24 -16
- data/lib/geocoder/results/pc_miler.rb +98 -0
- data/lib/geocoder/results/pdok_nl.rb +62 -0
- data/lib/geocoder/results/photon.rb +119 -0
- data/lib/geocoder/results/twogis.rb +76 -0
- data/lib/geocoder/version.rb +1 -1
- data/lib/maxmind_database.rb +12 -12
- data/lib/tasks/maxmind.rake +1 -1
- metadata +65 -11
- data/examples/autoexpire_cache_dalli.rb +0 -62
- data/examples/autoexpire_cache_redis.rb +0 -30
- data/lib/geocoder/lookups/dstk.rb +0 -22
- data/lib/geocoder/results/dstk.rb +0 -6
@@ -17,14 +17,16 @@ module Geocoder::Lookup
|
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
|
-
def query_url(query)
|
21
|
-
"#{protocol}://#{host}/json/#{query.sanitized_text}"
|
22
|
-
end
|
23
|
-
|
24
20
|
private # ---------------------------------------------------------------
|
25
21
|
|
26
|
-
def
|
27
|
-
|
22
|
+
def base_query_url(query)
|
23
|
+
"#{protocol}://#{host}/json/#{query.sanitized_text}?"
|
24
|
+
end
|
25
|
+
|
26
|
+
def query_url_params(query)
|
27
|
+
{
|
28
|
+
:apikey => configuration.api_key
|
29
|
+
}.merge(super)
|
28
30
|
end
|
29
31
|
|
30
32
|
def parse_raw_data(raw_data)
|
@@ -0,0 +1,78 @@
|
|
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 = if query.reverse_geocode?
|
26
|
+
'reverse'
|
27
|
+
elsif query.options[:autocomplete]
|
28
|
+
'autocomplete'
|
29
|
+
else
|
30
|
+
'search'
|
31
|
+
end
|
32
|
+
"https://api.geoapify.com/v1/geocode/#{method}?"
|
33
|
+
end
|
34
|
+
|
35
|
+
def results(query)
|
36
|
+
return [] unless (doc = fetch_data(query))
|
37
|
+
|
38
|
+
# The rest of the status codes should be already handled by the default
|
39
|
+
# functionality as the API returns correct HTTP response codes in most
|
40
|
+
# cases. There may be some unhandled cases still (such as over query
|
41
|
+
# limit reached) but there is not enough documentation to cover them.
|
42
|
+
case doc['statusCode']
|
43
|
+
when 500
|
44
|
+
raise_error(Geocoder::InvalidRequest) || Geocoder.log(:warn, doc['message'])
|
45
|
+
end
|
46
|
+
|
47
|
+
return [] unless doc['type'] == 'FeatureCollection'
|
48
|
+
return [] unless doc['features'] || doc['features'].present?
|
49
|
+
|
50
|
+
doc['features']
|
51
|
+
end
|
52
|
+
|
53
|
+
def query_url_params(query)
|
54
|
+
lang = query.language || configuration.language
|
55
|
+
params = { apiKey: configuration.api_key, lang: lang, limit: query.options[:limit] }
|
56
|
+
|
57
|
+
if query.reverse_geocode?
|
58
|
+
params.merge!(query_url_params_reverse(query))
|
59
|
+
else
|
60
|
+
params.merge!(query_url_params_coordinates(query))
|
61
|
+
end
|
62
|
+
|
63
|
+
params.merge!(super)
|
64
|
+
end
|
65
|
+
|
66
|
+
def query_url_params_coordinates(query)
|
67
|
+
{ text: query.sanitized_text }
|
68
|
+
end
|
69
|
+
|
70
|
+
def query_url_params_reverse(query)
|
71
|
+
{
|
72
|
+
lat: query.coordinates[0],
|
73
|
+
lon: query.coordinates[1]
|
74
|
+
}
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
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
|
@@ -33,9 +33,29 @@ module Geocoder
|
|
33
33
|
result
|
34
34
|
end
|
35
35
|
|
36
|
+
def fields(query)
|
37
|
+
if query.options.has_key?(:fields)
|
38
|
+
return format_fields(query.options[:fields])
|
39
|
+
end
|
40
|
+
|
41
|
+
if configuration.has_key?(:fields)
|
42
|
+
return format_fields(configuration[:fields])
|
43
|
+
end
|
44
|
+
|
45
|
+
nil # use Google Places defaults
|
46
|
+
end
|
47
|
+
|
48
|
+
def format_fields(*fields)
|
49
|
+
flattened = fields.flatten.compact
|
50
|
+
return if flattened.empty?
|
51
|
+
|
52
|
+
flattened.join(',')
|
53
|
+
end
|
54
|
+
|
36
55
|
def query_url_google_params(query)
|
37
56
|
{
|
38
57
|
placeid: query.text,
|
58
|
+
fields: fields(query),
|
39
59
|
language: query.language || configuration.language
|
40
60
|
}
|
41
61
|
end
|
@@ -31,28 +31,44 @@ module Geocoder
|
|
31
31
|
input: query.text,
|
32
32
|
inputtype: 'textquery',
|
33
33
|
fields: fields(query),
|
34
|
+
locationbias: locationbias(query),
|
34
35
|
language: query.language || configuration.language
|
35
36
|
}
|
36
37
|
end
|
37
38
|
|
38
39
|
def fields(query)
|
39
|
-
|
40
|
-
|
40
|
+
if query.options.has_key?(:fields)
|
41
|
+
return format_fields(query.options[:fields])
|
42
|
+
end
|
43
|
+
|
44
|
+
if configuration.has_key?(:fields)
|
45
|
+
return format_fields(configuration[:fields])
|
46
|
+
end
|
41
47
|
|
42
48
|
default_fields
|
43
49
|
end
|
44
50
|
|
45
51
|
def default_fields
|
46
|
-
legacy = %w[id reference]
|
47
52
|
basic = %w[business_status formatted_address geometry icon name
|
48
53
|
photos place_id plus_code types]
|
49
54
|
contact = %w[opening_hours]
|
50
55
|
atmosphere = %W[price_level rating user_ratings_total]
|
51
|
-
format_fields(
|
56
|
+
format_fields(basic, contact, atmosphere)
|
52
57
|
end
|
53
58
|
|
54
59
|
def format_fields(*fields)
|
55
|
-
fields.flatten.
|
60
|
+
flattened = fields.flatten.compact
|
61
|
+
return if flattened.empty?
|
62
|
+
|
63
|
+
flattened.join(',')
|
64
|
+
end
|
65
|
+
|
66
|
+
def locationbias(query)
|
67
|
+
if query.options.has_key?(:locationbias)
|
68
|
+
query.options[:locationbias]
|
69
|
+
else
|
70
|
+
configuration[:locationbias]
|
71
|
+
end
|
56
72
|
end
|
57
73
|
end
|
58
74
|
end
|
@@ -19,50 +19,55 @@ module Geocoder::Lookup
|
|
19
19
|
private # ---------------------------------------------------------------
|
20
20
|
|
21
21
|
def base_query_url(query)
|
22
|
-
|
22
|
+
service = query.reverse_geocode? ? "revgeocode" : "geocode"
|
23
|
+
|
24
|
+
"#{protocol}://#{service}.search.hereapi.com/v1/#{service}?"
|
23
25
|
end
|
24
26
|
|
25
27
|
def results(query)
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
return [] if r.nil? || !r.is_a?(Array) || r.empty?
|
30
|
-
return r.first['Result']
|
28
|
+
unless configuration.api_key.is_a?(String)
|
29
|
+
api_key_not_string!
|
30
|
+
return []
|
31
31
|
end
|
32
|
-
[]
|
32
|
+
return [] unless doc = fetch_data(query)
|
33
|
+
return [] if doc["items"].nil?
|
34
|
+
|
35
|
+
doc["items"]
|
33
36
|
end
|
34
37
|
|
35
38
|
def query_url_here_options(query, reverse_geocode)
|
36
39
|
options = {
|
37
|
-
|
38
|
-
|
39
|
-
language: (query.language || configuration.language)
|
40
|
+
apiKey: configuration.api_key,
|
41
|
+
lang: (query.language || configuration.language)
|
40
42
|
}
|
41
|
-
if reverse_geocode
|
42
|
-
options[:mode] = :retrieveAddresses
|
43
|
-
return options
|
44
|
-
end
|
43
|
+
return options if reverse_geocode
|
45
44
|
|
46
45
|
unless (country = query.options[:country]).nil?
|
47
|
-
options[:
|
46
|
+
options[:in] = "countryCode:#{country}"
|
48
47
|
end
|
49
48
|
|
50
|
-
unless (mapview = query.options[:bounds]).nil?
|
51
|
-
options[:mapview] = mapview.map{ |point| "%f,%f" % point }.join(';')
|
52
|
-
end
|
53
49
|
options
|
54
50
|
end
|
55
51
|
|
56
52
|
def query_url_params(query)
|
57
53
|
if query.reverse_geocode?
|
58
54
|
super.merge(query_url_here_options(query, true)).merge(
|
59
|
-
|
55
|
+
at: query.sanitized_text
|
60
56
|
)
|
61
57
|
else
|
62
58
|
super.merge(query_url_here_options(query, false)).merge(
|
63
|
-
|
59
|
+
q: query.sanitized_text
|
64
60
|
)
|
65
61
|
end
|
66
62
|
end
|
63
|
+
|
64
|
+
def api_key_not_string!
|
65
|
+
msg = <<~MSG
|
66
|
+
API key for HERE Geocoding and Search API should be a string.
|
67
|
+
For more info on how to obtain it, please see https://developer.here.com/documentation/identity-access-management/dev_guide/topics/plat-using-apikeys.html
|
68
|
+
MSG
|
69
|
+
|
70
|
+
raise_error(Geocoder::ConfigurationError, msg) || Geocoder.log(:warn, msg)
|
71
|
+
end
|
67
72
|
end
|
68
73
|
end
|
@@ -8,6 +8,10 @@ module Geocoder::Lookup
|
|
8
8
|
"IP2LocationApi"
|
9
9
|
end
|
10
10
|
|
11
|
+
def required_api_key_parts
|
12
|
+
['key']
|
13
|
+
end
|
14
|
+
|
11
15
|
def supported_protocols
|
12
16
|
[:http, :https]
|
13
17
|
end
|
@@ -15,15 +19,15 @@ module Geocoder::Lookup
|
|
15
19
|
private # ----------------------------------------------------------------
|
16
20
|
|
17
21
|
def base_query_url(query)
|
18
|
-
"#{protocol}://api.ip2location.com/?"
|
22
|
+
"#{protocol}://api.ip2location.com/v2/?"
|
19
23
|
end
|
20
24
|
|
21
25
|
def query_url_params(query)
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
26
|
+
super.merge(
|
27
|
+
key: configuration.api_key,
|
28
|
+
ip: query.sanitized_text,
|
29
|
+
package: configuration[:package],
|
30
|
+
)
|
27
31
|
end
|
28
32
|
|
29
33
|
def results(query)
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'geocoder/lookups/base'
|
2
|
+
require 'geocoder/results/ip2location_io'
|
3
|
+
|
4
|
+
module Geocoder::Lookup
|
5
|
+
class Ip2locationIo < Base
|
6
|
+
|
7
|
+
def name
|
8
|
+
"IP2LocationIOApi"
|
9
|
+
end
|
10
|
+
|
11
|
+
def required_api_key_parts
|
12
|
+
['key']
|
13
|
+
end
|
14
|
+
|
15
|
+
def supported_protocols
|
16
|
+
[:http, :https]
|
17
|
+
end
|
18
|
+
|
19
|
+
private # ----------------------------------------------------------------
|
20
|
+
|
21
|
+
def base_query_url(query)
|
22
|
+
"#{protocol}://api.ip2location.io/?"
|
23
|
+
end
|
24
|
+
|
25
|
+
def query_url_params(query)
|
26
|
+
super.merge(
|
27
|
+
key: configuration.api_key,
|
28
|
+
ip: query.sanitized_text,
|
29
|
+
)
|
30
|
+
end
|
31
|
+
|
32
|
+
def results(query)
|
33
|
+
# don't look up a loopback or private address, just return the stored result
|
34
|
+
return [reserved_result(query.text)] if query.internal_ip_address?
|
35
|
+
return [] unless doc = fetch_data(query)
|
36
|
+
if doc["response"] == "INVALID ACCOUNT"
|
37
|
+
raise_error(Geocoder::InvalidApiKey) || Geocoder.log(:warn, "INVALID ACCOUNT")
|
38
|
+
return []
|
39
|
+
else
|
40
|
+
return [doc]
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def reserved_result(query)
|
45
|
+
{
|
46
|
+
"ip" => "-",
|
47
|
+
"country_code" => "-",
|
48
|
+
"country_name" => "-",
|
49
|
+
"region_name" => "-",
|
50
|
+
"city_name" => "-",
|
51
|
+
"latitude" => null,
|
52
|
+
"longitude" => null,
|
53
|
+
"zip_code" => "-",
|
54
|
+
"time_zone" => "-",
|
55
|
+
"asn" => "-",
|
56
|
+
"as" => "-",
|
57
|
+
"is_proxy" => false
|
58
|
+
}
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'geocoder/lookups/base'
|
2
|
+
require 'geocoder/results/ip2location_lite'
|
3
|
+
|
4
|
+
module Geocoder
|
5
|
+
module Lookup
|
6
|
+
class Ip2locationLite < Base
|
7
|
+
attr_reader :gem_name
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
unless configuration[:file].nil?
|
11
|
+
begin
|
12
|
+
@gem_name = 'ip2location_ruby'
|
13
|
+
require @gem_name
|
14
|
+
rescue LoadError
|
15
|
+
raise "Could not load IP2Location DB dependency. To use the IP2LocationLite lookup you must add the #{@gem_name} gem to your Gemfile or have it installed in your system."
|
16
|
+
end
|
17
|
+
end
|
18
|
+
super
|
19
|
+
end
|
20
|
+
|
21
|
+
def name
|
22
|
+
'IP2LocationLite'
|
23
|
+
end
|
24
|
+
|
25
|
+
def required_api_key_parts
|
26
|
+
[]
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def results(query)
|
32
|
+
return [] unless configuration[:file]
|
33
|
+
|
34
|
+
i2l = Ip2location.new.open(configuration[:file].to_s)
|
35
|
+
result = i2l.get_all(query.to_s)
|
36
|
+
result.nil? ? [] : [result]
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'geocoder/lookups/base'
|
2
|
+
require 'geocoder/results/ipbase'
|
3
|
+
|
4
|
+
module Geocoder::Lookup
|
5
|
+
class Ipbase < Base
|
6
|
+
|
7
|
+
def name
|
8
|
+
"ipbase.com"
|
9
|
+
end
|
10
|
+
|
11
|
+
def supported_protocols
|
12
|
+
[:https]
|
13
|
+
end
|
14
|
+
|
15
|
+
private # ---------------------------------------------------------------
|
16
|
+
|
17
|
+
def base_query_url(query)
|
18
|
+
"https://api.ipbase.com/v2/info?"
|
19
|
+
end
|
20
|
+
|
21
|
+
def query_url_params(query)
|
22
|
+
{
|
23
|
+
:ip => query.sanitized_text,
|
24
|
+
:apikey => configuration.api_key
|
25
|
+
}
|
26
|
+
end
|
27
|
+
|
28
|
+
def results(query)
|
29
|
+
# don't look up a loopback or private address, just return the stored result
|
30
|
+
return [reserved_result(query.text)] if query.internal_ip_address?
|
31
|
+
doc = fetch_data(query) || {}
|
32
|
+
doc.fetch("data", {})["location"] ? [doc] : []
|
33
|
+
end
|
34
|
+
|
35
|
+
def reserved_result(ip)
|
36
|
+
{
|
37
|
+
"data" => {
|
38
|
+
"ip" => ip,
|
39
|
+
"location" => {
|
40
|
+
"city" => { "name" => "" },
|
41
|
+
"country" => { "alpha2" => "RD", "name" => "Reserved" },
|
42
|
+
"region" => { "alpha2" => "", "name" => "" },
|
43
|
+
"zip" => ""
|
44
|
+
}
|
45
|
+
}
|
46
|
+
}
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'geocoder/lookups/base'
|
4
|
+
require 'geocoder/results/ipqualityscore'
|
5
|
+
|
6
|
+
module Geocoder::Lookup
|
7
|
+
class Ipqualityscore < Base
|
8
|
+
|
9
|
+
def name
|
10
|
+
"IPQualityScore"
|
11
|
+
end
|
12
|
+
|
13
|
+
def required_api_key_parts
|
14
|
+
['api_key']
|
15
|
+
end
|
16
|
+
|
17
|
+
private # ---------------------------------------------------------------
|
18
|
+
|
19
|
+
def base_query_url(query)
|
20
|
+
"#{protocol}://ipqualityscore.com/api/json/ip/#{configuration.api_key}/#{query.sanitized_text}?"
|
21
|
+
end
|
22
|
+
|
23
|
+
def valid_response?(response)
|
24
|
+
if (json = parse_json(response.body))
|
25
|
+
success = json['success']
|
26
|
+
end
|
27
|
+
super && success == true
|
28
|
+
end
|
29
|
+
|
30
|
+
def results(query, reverse = false)
|
31
|
+
return [] unless doc = fetch_data(query)
|
32
|
+
|
33
|
+
return [doc] if doc['success']
|
34
|
+
|
35
|
+
case doc['message']
|
36
|
+
when /invalid (.*) key/i
|
37
|
+
raise_error Geocoder::InvalidApiKey ||
|
38
|
+
Geocoder.log(:warn, "#{name} API error: invalid api key.")
|
39
|
+
when /insufficient credits/, /exceeded your request quota/
|
40
|
+
raise_error Geocoder::OverQueryLimitError ||
|
41
|
+
Geocoder.log(:warn, "#{name} API error: query limit exceeded.")
|
42
|
+
when /invalid (.*) address/i
|
43
|
+
raise_error Geocoder::InvalidRequest ||
|
44
|
+
Geocoder.log(:warn, "#{name} API error: invalid request.")
|
45
|
+
end
|
46
|
+
|
47
|
+
[doc]
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -11,6 +11,10 @@ module Geocoder::Lookup
|
|
11
11
|
["api_key"]
|
12
12
|
end
|
13
13
|
|
14
|
+
def supported_protocols
|
15
|
+
[:https]
|
16
|
+
end
|
17
|
+
|
14
18
|
private # ----------------------------------------------------------------
|
15
19
|
|
16
20
|
def base_query_url(query)
|
@@ -25,7 +29,7 @@ module Geocoder::Lookup
|
|
25
29
|
end
|
26
30
|
|
27
31
|
def configured_host
|
28
|
-
configuration[:host] || "locationiq.
|
32
|
+
configuration[:host] || "us1.locationiq.com"
|
29
33
|
end
|
30
34
|
|
31
35
|
def results(query)
|
@@ -30,14 +30,14 @@ module Geocoder::Lookup
|
|
30
30
|
end
|
31
31
|
|
32
32
|
def mapbox_search_term(query)
|
33
|
-
require '
|
33
|
+
require 'erb' unless defined?(ERB) && defined?(ERB::Util.url_encode)
|
34
34
|
if query.reverse_geocode?
|
35
35
|
lat,lon = query.coordinates
|
36
|
-
"#{
|
36
|
+
"#{ERB::Util.url_encode lon},#{ERB::Util.url_encode lat}"
|
37
37
|
else
|
38
38
|
# truncate at first semicolon so Mapbox doesn't go into batch mode
|
39
39
|
# (see Github issue #1299)
|
40
|
-
|
40
|
+
ERB::Util.url_encode query.text.to_s.split(';').first.to_s
|
41
41
|
end
|
42
42
|
end
|
43
43
|
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'geocoder/lookups/base'
|
2
|
+
require "geocoder/results/melissa_street"
|
3
|
+
|
4
|
+
module Geocoder::Lookup
|
5
|
+
class MelissaStreet < Base
|
6
|
+
|
7
|
+
def name
|
8
|
+
"MelissaStreet"
|
9
|
+
end
|
10
|
+
|
11
|
+
def results(query)
|
12
|
+
return [] unless doc = fetch_data(query)
|
13
|
+
|
14
|
+
if doc["TransmissionResults"] == "GE05"
|
15
|
+
raise_error(Geocoder::InvalidApiKey) ||
|
16
|
+
Geocoder.log(:warn, "Melissa service error: invalid API key.")
|
17
|
+
end
|
18
|
+
|
19
|
+
return doc["Records"]
|
20
|
+
end
|
21
|
+
|
22
|
+
private # ---------------------------------------------------------------
|
23
|
+
|
24
|
+
def base_query_url(query)
|
25
|
+
"#{protocol}://address.melissadata.net/v3/WEB/GlobalAddress/doGlobalAddress?"
|
26
|
+
end
|
27
|
+
|
28
|
+
def query_url_params(query)
|
29
|
+
params = {
|
30
|
+
id: configuration.api_key,
|
31
|
+
format: "JSON",
|
32
|
+
a1: query.sanitized_text,
|
33
|
+
loc: query.options[:city],
|
34
|
+
admarea: query.options[:state],
|
35
|
+
postal: query.options[:postal],
|
36
|
+
ctry: query.options[:country]
|
37
|
+
}
|
38
|
+
params.merge(super)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|