geocoder 1.5.0 → 1.5.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of geocoder might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +8 -2
- data/README.md +7 -7
- data/lib/geocoder/calculations.rb +1 -1
- data/lib/geocoder/ip_address.rb +13 -0
- data/lib/geocoder/lookup.rb +1 -1
- data/lib/geocoder/lookups/baidu_ip.rb +1 -1
- data/lib/geocoder/lookups/base.rb +5 -2
- data/lib/geocoder/lookups/bing.rb +2 -1
- data/lib/geocoder/lookups/esri.rb +38 -13
- data/lib/geocoder/lookups/freegeoip.rb +3 -3
- data/lib/geocoder/lookups/here.rb +26 -11
- data/lib/geocoder/lookups/ip2location.rb +2 -1
- data/lib/geocoder/lookups/ipapi_com.rb +2 -1
- data/lib/geocoder/lookups/ipdata_co.rb +5 -4
- data/lib/geocoder/lookups/ipinfo_io.rb +2 -11
- data/lib/geocoder/lookups/ipstack.rb +2 -2
- data/lib/geocoder/lookups/maxmind.rb +2 -2
- data/lib/geocoder/lookups/maxmind_geoip2.rb +4 -7
- data/lib/geocoder/lookups/pelias.rb +2 -3
- data/lib/geocoder/lookups/pointpin.rb +3 -3
- data/lib/geocoder/lookups/smarty_streets.rb +13 -3
- data/lib/geocoder/lookups/telize.rb +2 -2
- data/lib/geocoder/lookups/tencent.rb +59 -0
- data/lib/geocoder/query.rb +14 -0
- data/lib/geocoder/railtie.rb +1 -1
- data/lib/geocoder/results/smarty_streets.rb +48 -18
- data/lib/geocoder/results/tencent.rb +72 -0
- data/lib/geocoder/stores/active_record.rb +1 -1
- data/lib/geocoder/version.rb +1 -1
- metadata +4 -4
- data/lib/geocoder/lookups/mapzen.rb +0 -15
- data/lib/geocoder/results/mapzen.rb +0 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e556ddf944bdad35735def9028fafebcf61ee294
|
4
|
+
data.tar.gz: a64476b63f73c13f24e385bc090193422bb92faa
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '08394b88099374e31e32306a418865b2ffecc4df707044e277072b99d9cadc6f92e1acd70fc18884128f381e28c2c42571f66eb3968a983e214a5a1ca89cf839'
|
7
|
+
data.tar.gz: 87dadf53fe66e26c2f3eec8bfc671b9cebaf76f50bd08f815ae8b08592bd2c87aab8fa1812ef07b282805383b81e93f9777d5224b5c86ebe412f6261fb9fe943
|
data/CHANGELOG.md
CHANGED
@@ -3,10 +3,16 @@ Changelog
|
|
3
3
|
|
4
4
|
Major changes to Geocoder for each release. Please see the Git log for complete list of changes.
|
5
5
|
|
6
|
-
1.5.
|
6
|
+
1.5.1 (2019 Jan 23)
|
7
7
|
-------------------
|
8
|
+
* Add support for :tencent lookup (thanks github.com/Anders-E).
|
9
|
+
* Add support for :smarty_streets international API (thanks github.com/ankane).
|
10
|
+
* Remove :mapzen lookup.
|
11
|
+
|
12
|
+
1.5.0 (2018 Jul 31)
|
13
|
+
-------------------
|
14
|
+
* Drop support for Ruby <2.0.
|
8
15
|
* Change default street address lookup from :google to :nominatim.
|
9
|
-
* Drop support for Ruby 1.9.
|
10
16
|
* Cache keys no longer include API credentials. This means many entries in existing cache implementations will be invalidated.
|
11
17
|
* Test lookup fixtures should now return `coordinates` and NOT `latitude`/`longitude` attributes (see #1258). This may break some people's tests.
|
12
18
|
* Add support for :ip2location lookup (thanks github.com/ip2location).
|
data/README.md
CHANGED
@@ -13,7 +13,7 @@ Key features:
|
|
13
13
|
|
14
14
|
* Forward and reverse geocoding, and IP address geocoding.
|
15
15
|
* Connects to more than 40 APIs worldwide.
|
16
|
-
* Performance-enhancing
|
16
|
+
* Performance-enhancing features like caching.
|
17
17
|
* Advanced configuration allows different parameters and APIs to be used in different conditions.
|
18
18
|
* Integrates with ActiveRecord and Mongoid.
|
19
19
|
* Basic geospatial queries: search within radius (or rectangle, or ring).
|
@@ -45,7 +45,7 @@ Advanced Features:
|
|
45
45
|
* [Geospatial Calculations](#geospatial-calculations)
|
46
46
|
* [Batch Geocoding](#batch-geocoding)
|
47
47
|
* [Testing](#testing)
|
48
|
-
* [Error Handling](#error-
|
48
|
+
* [Error Handling](#error-handling)
|
49
49
|
* [Command Line Interface](#command-line-interface)
|
50
50
|
|
51
51
|
The Rest:
|
@@ -224,15 +224,15 @@ Some common options are:
|
|
224
224
|
Please see [`lib/geocoder/configuration.rb`](https://github.com/alexreisner/geocoder/blob/master/lib/geocoder/configuration.rb) for a complete list of configuration options. Additionally, some lookups have their own special configuration options which are directly supported by Geocoder. For example, to specify a value for Google's `bounds` parameter:
|
225
225
|
|
226
226
|
# with Google:
|
227
|
-
Geocoder.search("
|
227
|
+
Geocoder.search("Middletown", bounds: [[40.6,-77.9], [39.9,-75.9]])
|
228
228
|
|
229
229
|
Please see the [source code for each lookup](https://github.com/alexreisner/geocoder/tree/master/lib/geocoder/lookups) to learn about directly supported parameters. Parameters which are not directly supported can be specified using the `:params` option, which appends options to the query string of the geocoding request. For example:
|
230
230
|
|
231
231
|
# Nominatim's `countrycodes` parameter:
|
232
|
-
Geocoder.search("
|
232
|
+
Geocoder.search("Rome", params: {countrycodes: "us,ca"})
|
233
233
|
|
234
234
|
# Google's `region` parameter:
|
235
|
-
Geocoder.search("
|
235
|
+
Geocoder.search("Rome", params: {region: "..."})
|
236
236
|
|
237
237
|
### Configuring Multiple Services
|
238
238
|
|
@@ -500,9 +500,9 @@ To avoid exceeding per-day limits you can add a `LIMIT` option. However, this wi
|
|
500
500
|
Testing
|
501
501
|
-------
|
502
502
|
|
503
|
-
When writing tests for an app that uses Geocoder it may be useful to avoid network calls and have Geocoder return consistent, configurable results. To do this, configure the `:test` lookup
|
503
|
+
When writing tests for an app that uses Geocoder it may be useful to avoid network calls and have Geocoder return consistent, configurable results. To do this, configure the `:test` lookup and/or `:ip_lookup`
|
504
504
|
|
505
|
-
Geocoder.configure(lookup: :test)
|
505
|
+
Geocoder.configure(lookup: :test, ip_lookup: :test)
|
506
506
|
|
507
507
|
Add stubs to define the results that will be returned:
|
508
508
|
|
@@ -154,7 +154,7 @@ module Geocoder
|
|
154
154
|
# Translate a bearing (float) into a compass direction (string, eg "North").
|
155
155
|
#
|
156
156
|
def compass_point(bearing, points = COMPASS_POINTS)
|
157
|
-
seg_size = 360 / points.size
|
157
|
+
seg_size = 360.0 / points.size
|
158
158
|
points[((bearing + (seg_size / 2)) % 360) / seg_size]
|
159
159
|
end
|
160
160
|
|
data/lib/geocoder/ip_address.rb
CHANGED
@@ -1,11 +1,24 @@
|
|
1
1
|
require 'resolv'
|
2
2
|
module Geocoder
|
3
3
|
class IpAddress < String
|
4
|
+
PRIVATE_IPS = [
|
5
|
+
'10.0.0.0/8',
|
6
|
+
'172.16.0.0/12',
|
7
|
+
'192.168.0.0/16',
|
8
|
+
].map { |ip| IPAddr.new(ip) }.freeze
|
9
|
+
|
10
|
+
def internal?
|
11
|
+
loopback? || private?
|
12
|
+
end
|
4
13
|
|
5
14
|
def loopback?
|
6
15
|
valid? and !!(self == "0.0.0.0" or self.match(/\A127\./) or self == "::1")
|
7
16
|
end
|
8
17
|
|
18
|
+
def private?
|
19
|
+
valid? && PRIVATE_IPS.any? { |ip| ip.include?(self) }
|
20
|
+
end
|
21
|
+
|
9
22
|
def valid?
|
10
23
|
!!((self =~ Resolv::IPv4::Regex) || (self =~ Resolv::IPv6::Regex))
|
11
24
|
end
|
data/lib/geocoder/lookup.rb
CHANGED
@@ -164,7 +164,7 @@ module Geocoder
|
|
164
164
|
def cache_key_params(query)
|
165
165
|
# omit api_key and token because they may vary among requests
|
166
166
|
query_url_params(query).reject do |key,value|
|
167
|
-
key.to_s.match
|
167
|
+
key.to_s.match(/(key|token)/)
|
168
168
|
end
|
169
169
|
end
|
170
170
|
|
@@ -209,7 +209,10 @@ module Geocoder
|
|
209
209
|
JSON.parse(data)
|
210
210
|
end
|
211
211
|
rescue
|
212
|
-
raise_error(ResponseParseError.new(data))
|
212
|
+
unless raise_error(ResponseParseError.new(data))
|
213
|
+
Geocoder.log(:warn, "Geocoding API's response was not valid JSON")
|
214
|
+
Geocoder.log(:debug, "Raw response: #{data}")
|
215
|
+
end
|
213
216
|
end
|
214
217
|
|
215
218
|
##
|
@@ -40,31 +40,56 @@ module Geocoder::Lookup
|
|
40
40
|
else
|
41
41
|
params[:text] = query.sanitized_text
|
42
42
|
end
|
43
|
-
|
44
|
-
params[:
|
43
|
+
|
44
|
+
params[:token] = token(query)
|
45
|
+
|
46
|
+
if for_storage_value = for_storage(query)
|
47
|
+
params[:forStorage] = for_storage_value
|
48
|
+
end
|
45
49
|
params[:sourceCountry] = configuration[:source_country] if configuration[:source_country]
|
46
50
|
params.merge(super)
|
47
51
|
end
|
48
52
|
|
49
|
-
def
|
50
|
-
|
51
|
-
|
53
|
+
def for_storage(query)
|
54
|
+
if query.options.has_key?(:for_storage)
|
55
|
+
query.options[:for_storage]
|
56
|
+
else
|
57
|
+
configuration[:for_storage]
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def token(query)
|
62
|
+
token_instance = if query.options[:token]
|
63
|
+
query.options[:token]
|
64
|
+
else
|
65
|
+
configuration[:token]
|
66
|
+
end
|
67
|
+
|
68
|
+
if !valid_token_configured?(token_instance) && configuration.api_key
|
69
|
+
token_instance = create_and_save_token!(query)
|
70
|
+
end
|
71
|
+
|
72
|
+
token_instance.to_s unless token_instance.nil?
|
52
73
|
end
|
53
74
|
|
54
|
-
def valid_token_configured?
|
55
|
-
!
|
75
|
+
def valid_token_configured?(token_instance)
|
76
|
+
!token_instance.nil? && token_instance.active?
|
56
77
|
end
|
57
78
|
|
58
|
-
def create_and_save_token!
|
59
|
-
|
79
|
+
def create_and_save_token!(query)
|
80
|
+
token_instance = create_token
|
81
|
+
|
82
|
+
if query.options[:token]
|
83
|
+
query.options[:token] = token_instance
|
84
|
+
else
|
85
|
+
Geocoder.merge_into_lookup_config(:esri, token: token_instance)
|
86
|
+
end
|
87
|
+
|
88
|
+
token_instance
|
60
89
|
end
|
61
90
|
|
62
91
|
def create_token
|
63
92
|
Geocoder::EsriToken.generate_token(*configuration.api_key)
|
64
93
|
end
|
65
|
-
|
66
|
-
def save_token!(token_instance)
|
67
|
-
Geocoder.merge_into_lookup_config(:esri, token: token_instance)
|
68
|
-
end
|
69
94
|
end
|
70
95
|
end
|
@@ -7,7 +7,7 @@ module Geocoder::Lookup
|
|
7
7
|
def name
|
8
8
|
"FreeGeoIP"
|
9
9
|
end
|
10
|
-
|
10
|
+
|
11
11
|
def supported_protocols
|
12
12
|
if configuration[:host]
|
13
13
|
[:http, :https]
|
@@ -32,8 +32,8 @@ module Geocoder::Lookup
|
|
32
32
|
end
|
33
33
|
|
34
34
|
def results(query)
|
35
|
-
# don't look up a loopback address, just return the stored result
|
36
|
-
return [reserved_result(query.text)] if query.
|
35
|
+
# don't look up a loopback or private address, just return the stored result
|
36
|
+
return [reserved_result(query.text)] if query.internal_ip_address?
|
37
37
|
# note: Freegeoip.net returns plain text "Not Found" on bad request
|
38
38
|
(doc = fetch_data(query)) ? [doc] : []
|
39
39
|
end
|
@@ -28,33 +28,48 @@ module Geocoder::Lookup
|
|
28
28
|
[]
|
29
29
|
end
|
30
30
|
|
31
|
-
def
|
31
|
+
def query_url_here_options(query, reverse_geocode)
|
32
32
|
options = {
|
33
|
-
:
|
34
|
-
:
|
35
|
-
:
|
33
|
+
gen: 9,
|
34
|
+
app_id: api_key,
|
35
|
+
app_code: api_code,
|
36
|
+
language: (query.language || configuration.language)
|
36
37
|
}
|
38
|
+
if reverse_geocode
|
39
|
+
options[:mode] = :retrieveAddresses
|
40
|
+
return options
|
41
|
+
end
|
42
|
+
|
43
|
+
unless (country = query.options[:country]).nil?
|
44
|
+
options[:country] = country
|
45
|
+
end
|
37
46
|
|
47
|
+
unless (mapview = query.options[:bounds]).nil?
|
48
|
+
options[:mapview] = mapview.map{ |point| "%f,%f" % point }.join(';')
|
49
|
+
end
|
50
|
+
options
|
51
|
+
end
|
52
|
+
|
53
|
+
def query_url_params(query)
|
38
54
|
if query.reverse_geocode?
|
39
|
-
super.merge(
|
40
|
-
:
|
41
|
-
:mode=>:retrieveAddresses
|
55
|
+
super.merge(query_url_here_options(query, true)).merge(
|
56
|
+
prox: query.sanitized_text
|
42
57
|
)
|
43
58
|
else
|
44
|
-
super.merge(
|
45
|
-
:
|
59
|
+
super.merge(query_url_here_options(query, false)).merge(
|
60
|
+
searchtext: query.sanitized_text
|
46
61
|
)
|
47
62
|
end
|
48
63
|
end
|
49
64
|
|
50
65
|
def api_key
|
51
|
-
if a=configuration.api_key
|
66
|
+
if (a = configuration.api_key)
|
52
67
|
return a.first if a.is_a?(Array)
|
53
68
|
end
|
54
69
|
end
|
55
70
|
|
56
71
|
def api_code
|
57
|
-
if a=configuration.api_key
|
72
|
+
if (a = configuration.api_key)
|
58
73
|
return a.last if a.is_a?(Array)
|
59
74
|
end
|
60
75
|
end
|
@@ -27,7 +27,8 @@ module Geocoder::Lookup
|
|
27
27
|
end
|
28
28
|
|
29
29
|
def results(query)
|
30
|
-
return
|
30
|
+
# don't look up a loopback or private address, just return the stored result
|
31
|
+
return [reserved_result(query.text)] if query.internal_ip_address?
|
31
32
|
return [] unless doc = fetch_data(query)
|
32
33
|
if doc["response"] == "INVALID ACCOUNT"
|
33
34
|
raise_error(Geocoder::InvalidApiKey) || Geocoder.log(:warn, "INVALID ACCOUNT")
|
@@ -34,7 +34,8 @@ module Geocoder::Lookup
|
|
34
34
|
end
|
35
35
|
|
36
36
|
def results(query)
|
37
|
-
return
|
37
|
+
# don't look up a loopback or private address, just return the stored result
|
38
|
+
return [reserved_result(query.text)] if query.internal_ip_address?
|
38
39
|
|
39
40
|
return [] unless doc = fetch_data(query)
|
40
41
|
|
@@ -13,7 +13,9 @@ module Geocoder::Lookup
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def query_url(query)
|
16
|
-
|
16
|
+
# Ipdata.co requires that the API key be sent as a query parameter.
|
17
|
+
# It no longer supports API keys sent as headers.
|
18
|
+
"#{protocol}://#{host}/#{query.sanitized_text}?api-key=#{configuration.api_key}"
|
17
19
|
end
|
18
20
|
|
19
21
|
private # ---------------------------------------------------------------
|
@@ -23,9 +25,8 @@ module Geocoder::Lookup
|
|
23
25
|
end
|
24
26
|
|
25
27
|
def results(query)
|
26
|
-
|
27
|
-
|
28
|
-
return [reserved_result(query.text)] if query.loopback_ip_address?
|
28
|
+
# don't look up a loopback or private address, just return the stored result
|
29
|
+
return [reserved_result(query.text)] if query.internal_ip_address?
|
29
30
|
# note: Ipdata.co returns plain text on bad request
|
30
31
|
(doc = fetch_data(query)) ? [doc] : []
|
31
32
|
end
|
@@ -8,15 +8,6 @@ module Geocoder::Lookup
|
|
8
8
|
"Ipinfo.io"
|
9
9
|
end
|
10
10
|
|
11
|
-
# HTTPS available only for paid plans
|
12
|
-
def supported_protocols
|
13
|
-
if configuration.api_key
|
14
|
-
[:http, :https]
|
15
|
-
else
|
16
|
-
[:http]
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
11
|
private # ---------------------------------------------------------------
|
21
12
|
|
22
13
|
def base_query_url(query)
|
@@ -26,8 +17,8 @@ module Geocoder::Lookup
|
|
26
17
|
end
|
27
18
|
|
28
19
|
def results(query)
|
29
|
-
# don't look up a loopback address, just return the stored result
|
30
|
-
return [reserved_result(query.text)] if query.
|
20
|
+
# don't look up a loopback or private address, just return the stored result
|
21
|
+
return [reserved_result(query.text)] if query.internal_ip_address?
|
31
22
|
|
32
23
|
if !(doc = fetch_data(query)).is_a?(Hash) or doc['error']
|
33
24
|
[]
|
@@ -34,8 +34,8 @@ module Geocoder::Lookup
|
|
34
34
|
end
|
35
35
|
|
36
36
|
def results(query)
|
37
|
-
# don't look up a loopback address, just return the stored result
|
38
|
-
return [reserved_result(query.text)] if query.
|
37
|
+
# don't look up a loopback or private address, just return the stored result
|
38
|
+
return [reserved_result(query.text)] if query.internal_ip_address?
|
39
39
|
|
40
40
|
return [] unless doc = fetch_data(query)
|
41
41
|
|
@@ -57,8 +57,8 @@ module Geocoder::Lookup
|
|
57
57
|
end
|
58
58
|
|
59
59
|
def results(query)
|
60
|
-
# don't look up a loopback address, just return the stored result
|
61
|
-
return [reserved_result] if query.
|
60
|
+
# don't look up a loopback or private address, just return the stored result
|
61
|
+
return [reserved_result] if query.internal_ip_address?
|
62
62
|
doc = fetch_data(query)
|
63
63
|
if doc and doc.is_a?(Array)
|
64
64
|
if !data_contains_error?(doc)
|
@@ -32,11 +32,7 @@ module Geocoder::Lookup
|
|
32
32
|
return s
|
33
33
|
else
|
34
34
|
raise(
|
35
|
-
Geocoder::ConfigurationError,
|
36
|
-
"When using MaxMind GeoIP2 you MUST specify a service name and basic_auth: " +
|
37
|
-
"Geocoder.configure(:maxmind_geoip2 => {:service => ...}, " +
|
38
|
-
":basic_auth => {:user ..., :password => ...}), " +
|
39
|
-
"where service is one of: #{services.inspect}"
|
35
|
+
Geocoder::ConfigurationError, "When using MaxMind GeoIP2 you must specify a service and credentials: Geocoder.configure(maxmind_geoip2: {service: ..., basic_auth: {user: ..., password: ...}}), where service is one of: #{services.inspect}"
|
40
36
|
)
|
41
37
|
end
|
42
38
|
end
|
@@ -57,8 +53,9 @@ module Geocoder::Lookup
|
|
57
53
|
end
|
58
54
|
|
59
55
|
def results(query)
|
60
|
-
# don't look up a loopback address
|
61
|
-
return [] if query.
|
56
|
+
# don't look up a loopback or private address, just return the stored result
|
57
|
+
return [] if query.internal_ip_address?
|
58
|
+
|
62
59
|
doc = fetch_data(query)
|
63
60
|
if doc
|
64
61
|
if !data_contains_error?(doc)
|
@@ -24,12 +24,11 @@ module Geocoder::Lookup
|
|
24
24
|
|
25
25
|
def query_url_params(query)
|
26
26
|
params = {
|
27
|
-
api_key: configuration.api_key
|
28
|
-
size: 1
|
27
|
+
api_key: configuration.api_key
|
29
28
|
}.merge(super)
|
30
29
|
|
31
30
|
if query.reverse_geocode?
|
32
|
-
lat,lon = query.coordinates
|
31
|
+
lat, lon = query.coordinates
|
33
32
|
params[:'point.lat'] = lat
|
34
33
|
params[:'point.lon'] = lon
|
35
34
|
else
|
@@ -23,8 +23,8 @@ module Geocoder::Lookup
|
|
23
23
|
end
|
24
24
|
|
25
25
|
def results(query)
|
26
|
-
# don't look up a loopback address, just return the stored result
|
27
|
-
return [] if query.
|
26
|
+
# don't look up a loopback or private address, just return the stored result
|
27
|
+
return [] if query.internal_ip_address?
|
28
28
|
doc = fetch_data(query)
|
29
29
|
if doc and doc.is_a?(Hash)
|
30
30
|
if !data_contains_error?(doc)
|
@@ -42,7 +42,7 @@ module Geocoder::Lookup
|
|
42
42
|
raise_error(Geocoder::Error) || Geocoder.log(:warn, "Pointpin server error")
|
43
43
|
end
|
44
44
|
end
|
45
|
-
|
45
|
+
|
46
46
|
return []
|
47
47
|
end
|
48
48
|
|
@@ -8,7 +8,7 @@ module Geocoder::Lookup
|
|
8
8
|
end
|
9
9
|
|
10
10
|
def required_api_key_parts
|
11
|
-
%w(
|
11
|
+
%w(auth-id auth-token)
|
12
12
|
end
|
13
13
|
|
14
14
|
# required by API as of 26 March 2015
|
@@ -19,7 +19,9 @@ module Geocoder::Lookup
|
|
19
19
|
private # ---------------------------------------------------------------
|
20
20
|
|
21
21
|
def base_query_url(query)
|
22
|
-
if
|
22
|
+
if international?(query)
|
23
|
+
"#{protocol}://international-street.api.smartystreets.com/verify?"
|
24
|
+
elsif zipcode_only?(query)
|
23
25
|
"#{protocol}://us-zipcode.api.smartystreets.com/lookup?"
|
24
26
|
else
|
25
27
|
"#{protocol}://us-street.api.smartystreets.com/street-address?"
|
@@ -30,9 +32,17 @@ module Geocoder::Lookup
|
|
30
32
|
!query.text.is_a?(Array) and query.to_s.strip =~ /\A\d{5}(-\d{4})?\Z/
|
31
33
|
end
|
32
34
|
|
35
|
+
def international?(query)
|
36
|
+
!query.options[:country].nil?
|
37
|
+
end
|
38
|
+
|
33
39
|
def query_url_params(query)
|
34
40
|
params = {}
|
35
|
-
if
|
41
|
+
if international?(query)
|
42
|
+
params[:freeform] = query.sanitized_text
|
43
|
+
params[:country] = query.options[:country]
|
44
|
+
params[:geocode] = true
|
45
|
+
elsif zipcode_only?(query)
|
36
46
|
params[:zipcode] = query.sanitized_text
|
37
47
|
else
|
38
48
|
params[:street] = query.sanitized_text
|
@@ -34,8 +34,8 @@ module Geocoder::Lookup
|
|
34
34
|
end
|
35
35
|
|
36
36
|
def results(query)
|
37
|
-
# don't look up a loopback address, just return the stored result
|
38
|
-
return [reserved_result(query.text)] if query.
|
37
|
+
# don't look up a loopback or private address, just return the stored result
|
38
|
+
return [reserved_result(query.text)] if query.internal_ip_address?
|
39
39
|
if (doc = fetch_data(query)).nil? or doc['code'] == 401 or empty_result?(doc)
|
40
40
|
[]
|
41
41
|
else
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'geocoder/lookups/base'
|
2
|
+
require "geocoder/results/tencent"
|
3
|
+
|
4
|
+
module Geocoder::Lookup
|
5
|
+
class Tencent < Base
|
6
|
+
|
7
|
+
def name
|
8
|
+
"Tencent"
|
9
|
+
end
|
10
|
+
|
11
|
+
def required_api_key_parts
|
12
|
+
["key"]
|
13
|
+
end
|
14
|
+
|
15
|
+
def supported_protocols
|
16
|
+
[:https]
|
17
|
+
end
|
18
|
+
|
19
|
+
private # ---------------------------------------------------------------
|
20
|
+
|
21
|
+
def base_query_url(query)
|
22
|
+
"#{protocol}://apis.map.qq.com/ws/geocoder/v1/?"
|
23
|
+
end
|
24
|
+
|
25
|
+
def content_key
|
26
|
+
'result'
|
27
|
+
end
|
28
|
+
|
29
|
+
def results(query, reverse = false)
|
30
|
+
return [] unless doc = fetch_data(query)
|
31
|
+
case doc['status']
|
32
|
+
when 0
|
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
|
+
when 311
|
44
|
+
raise_error(Geocoder::InvalidApiKey, "invalid api key") ||
|
45
|
+
Geocoder.log(:warn, "#{name} Geocoding API error: invalid api key.")
|
46
|
+
end
|
47
|
+
return []
|
48
|
+
end
|
49
|
+
|
50
|
+
def query_url_params(query)
|
51
|
+
{
|
52
|
+
(query.reverse_geocode? ? :location : :address) => query.sanitized_text,
|
53
|
+
:key => configuration.api_key,
|
54
|
+
:output => "json"
|
55
|
+
}.merge(super)
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
end
|
data/lib/geocoder/query.rb
CHANGED
@@ -66,6 +66,13 @@ module Geocoder
|
|
66
66
|
IpAddress.new(text).valid? rescue false
|
67
67
|
end
|
68
68
|
|
69
|
+
##
|
70
|
+
# Is the Query text a loopback or private IP address?
|
71
|
+
#
|
72
|
+
def internal_ip_address?
|
73
|
+
ip_address? && IpAddress.new(text).internal?
|
74
|
+
end
|
75
|
+
|
69
76
|
##
|
70
77
|
# Is the Query text a loopback IP address?
|
71
78
|
#
|
@@ -73,6 +80,13 @@ module Geocoder
|
|
73
80
|
ip_address? && IpAddress.new(text).loopback?
|
74
81
|
end
|
75
82
|
|
83
|
+
##
|
84
|
+
# Is the Query text a private IP address?
|
85
|
+
#
|
86
|
+
def private_ip_address?
|
87
|
+
ip_address? && IpAddress.new(text).private?
|
88
|
+
end
|
89
|
+
|
76
90
|
##
|
77
91
|
# Does the given string look like latitude/longitude coordinates?
|
78
92
|
#
|
data/lib/geocoder/railtie.rb
CHANGED
@@ -4,7 +4,7 @@ module Geocoder
|
|
4
4
|
if defined? Rails::Railtie
|
5
5
|
require 'rails'
|
6
6
|
class Railtie < Rails::Railtie
|
7
|
-
initializer 'geocoder.insert_into_active_record' do
|
7
|
+
initializer 'geocoder.insert_into_active_record', before: :load_config_initializers do
|
8
8
|
ActiveSupport.on_load :active_record do
|
9
9
|
Geocoder::Railtie.insert
|
10
10
|
end
|
@@ -15,51 +15,77 @@ module Geocoder::Result
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def address
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
18
|
+
parts =
|
19
|
+
if international_endpoint?
|
20
|
+
(1..12).map { |i| @data["address#{i}"] }
|
21
|
+
else
|
22
|
+
[
|
23
|
+
delivery_line_1,
|
24
|
+
delivery_line_2,
|
25
|
+
last_line
|
26
|
+
]
|
27
|
+
end
|
28
|
+
parts.select{ |i| i.to_s != "" }.join(" ")
|
23
29
|
end
|
24
30
|
|
25
31
|
def state
|
26
|
-
|
27
|
-
|
32
|
+
if international_endpoint?
|
33
|
+
components['administrative_area']
|
34
|
+
elsif zipcode_endpoint?
|
35
|
+
city_states.first['state']
|
36
|
+
else
|
28
37
|
components['state_abbreviation']
|
38
|
+
end
|
29
39
|
end
|
30
40
|
|
31
41
|
def state_code
|
32
|
-
|
33
|
-
|
42
|
+
if international_endpoint?
|
43
|
+
components['administrative_area']
|
44
|
+
elsif zipcode_endpoint?
|
45
|
+
city_states.first['state_abbreviation']
|
46
|
+
else
|
34
47
|
components['state_abbreviation']
|
48
|
+
end
|
35
49
|
end
|
36
50
|
|
37
51
|
def country
|
38
|
-
|
39
|
-
|
52
|
+
international_endpoint? ?
|
53
|
+
components['country_iso_3'] :
|
54
|
+
"United States"
|
40
55
|
end
|
41
56
|
|
42
57
|
def country_code
|
43
|
-
|
44
|
-
|
58
|
+
international_endpoint? ?
|
59
|
+
components['country_iso_3'] :
|
60
|
+
"US"
|
45
61
|
end
|
46
62
|
|
47
63
|
## Extra methods not in base.rb ------------------------
|
48
64
|
|
49
65
|
def street
|
50
|
-
|
66
|
+
international_endpoint? ?
|
67
|
+
components['thoroughfare_name'] :
|
68
|
+
components['street_name']
|
51
69
|
end
|
52
70
|
|
53
71
|
def city
|
54
|
-
|
55
|
-
|
72
|
+
if international_endpoint?
|
73
|
+
components['locality']
|
74
|
+
elsif zipcode_endpoint?
|
75
|
+
city_states.first['city']
|
76
|
+
else
|
56
77
|
components['city_name']
|
78
|
+
end
|
57
79
|
end
|
58
80
|
|
59
81
|
def zipcode
|
60
|
-
|
61
|
-
|
82
|
+
if international_endpoint?
|
83
|
+
components['postal_code']
|
84
|
+
elsif zipcode_endpoint?
|
85
|
+
zipcodes.first['zipcode']
|
86
|
+
else
|
62
87
|
components['zipcode']
|
88
|
+
end
|
63
89
|
end
|
64
90
|
alias_method :postal_code, :zipcode
|
65
91
|
|
@@ -78,6 +104,10 @@ module Geocoder::Result
|
|
78
104
|
zipcodes.any?
|
79
105
|
end
|
80
106
|
|
107
|
+
def international_endpoint?
|
108
|
+
!@data['address1'].nil?
|
109
|
+
end
|
110
|
+
|
81
111
|
[
|
82
112
|
:delivery_line_1,
|
83
113
|
:delivery_line_2,
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'geocoder/results/base'
|
2
|
+
|
3
|
+
module Geocoder::Result
|
4
|
+
class Tencent < Base
|
5
|
+
|
6
|
+
def coordinates
|
7
|
+
['lat', 'lng'].map{ |i| @data['location'][i] }
|
8
|
+
end
|
9
|
+
|
10
|
+
def address
|
11
|
+
"#{province}#{city}#{district}#{street}#{street_number}"
|
12
|
+
|
13
|
+
#@data['title'] or @data['address']
|
14
|
+
end
|
15
|
+
|
16
|
+
# NOTE: The Tencent reverse geocoding API has the field named
|
17
|
+
# 'address_component' compared to 'address_components' in the
|
18
|
+
# regular geocoding API.
|
19
|
+
def province
|
20
|
+
@data['address_components'] and (@data['address_components']['province']) or
|
21
|
+
(@data['address_component'] and @data['address_component']['province']) or
|
22
|
+
""
|
23
|
+
end
|
24
|
+
|
25
|
+
alias_method :state, :province
|
26
|
+
|
27
|
+
def city
|
28
|
+
@data['address_components'] and (@data['address_components']['city']) or
|
29
|
+
(@data['address_component'] and @data['address_component']['city']) or
|
30
|
+
""
|
31
|
+
end
|
32
|
+
|
33
|
+
def district
|
34
|
+
@data['address_components'] and (@data['address_components']['district']) or
|
35
|
+
(@data['address_component'] and @data['address_component']['district']) or
|
36
|
+
""
|
37
|
+
end
|
38
|
+
|
39
|
+
def street
|
40
|
+
@data['address_components'] and (@data['address_components']['street']) or
|
41
|
+
(@data['address_component'] and @data['address_component']['street']) or
|
42
|
+
""
|
43
|
+
end
|
44
|
+
|
45
|
+
def street_number
|
46
|
+
@data['address_components'] and (@data['address_components']['street_number']) or
|
47
|
+
(@data['address_component'] and @data['address_component']['street_number']) or
|
48
|
+
""
|
49
|
+
end
|
50
|
+
|
51
|
+
def address_components
|
52
|
+
@data['address_components'] or @data['address_component']
|
53
|
+
end
|
54
|
+
|
55
|
+
def state_code
|
56
|
+
""
|
57
|
+
end
|
58
|
+
|
59
|
+
def postal_code
|
60
|
+
""
|
61
|
+
end
|
62
|
+
|
63
|
+
def country
|
64
|
+
"China"
|
65
|
+
end
|
66
|
+
|
67
|
+
def country_code
|
68
|
+
"CN"
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
end
|
@@ -60,7 +60,7 @@ module Geocoder::Store
|
|
60
60
|
# corner followed by the northeast corner of the box
|
61
61
|
# (<tt>[[sw_lat, sw_lon], [ne_lat, ne_lon]]</tt>).
|
62
62
|
#
|
63
|
-
scope :within_bounding_box, lambda{
|
63
|
+
scope :within_bounding_box, lambda{ |*bounds|
|
64
64
|
sw_lat, sw_lng, ne_lat, ne_lng = bounds.flatten if bounds
|
65
65
|
if sw_lat && sw_lng && ne_lat && ne_lng
|
66
66
|
where(Geocoder::Sql.within_bounding_box(
|
data/lib/geocoder/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: geocoder
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.5.
|
4
|
+
version: 1.5.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alex Reisner
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2019-01-23 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Provides object geocoding (by street or IP address), reverse geocoding
|
14
14
|
(coordinates to street address), distance queries for ActiveRecord and Mongoid,
|
@@ -77,7 +77,6 @@ files:
|
|
77
77
|
- lib/geocoder/lookups/location_iq.rb
|
78
78
|
- lib/geocoder/lookups/mapbox.rb
|
79
79
|
- lib/geocoder/lookups/mapquest.rb
|
80
|
-
- lib/geocoder/lookups/mapzen.rb
|
81
80
|
- lib/geocoder/lookups/maxmind.rb
|
82
81
|
- lib/geocoder/lookups/maxmind_geoip2.rb
|
83
82
|
- lib/geocoder/lookups/maxmind_local.rb
|
@@ -90,6 +89,7 @@ files:
|
|
90
89
|
- lib/geocoder/lookups/postcodes_io.rb
|
91
90
|
- lib/geocoder/lookups/smarty_streets.rb
|
92
91
|
- lib/geocoder/lookups/telize.rb
|
92
|
+
- lib/geocoder/lookups/tencent.rb
|
93
93
|
- lib/geocoder/lookups/test.rb
|
94
94
|
- lib/geocoder/lookups/yandex.rb
|
95
95
|
- lib/geocoder/models/active_record.rb
|
@@ -129,7 +129,6 @@ files:
|
|
129
129
|
- lib/geocoder/results/location_iq.rb
|
130
130
|
- lib/geocoder/results/mapbox.rb
|
131
131
|
- lib/geocoder/results/mapquest.rb
|
132
|
-
- lib/geocoder/results/mapzen.rb
|
133
132
|
- lib/geocoder/results/maxmind.rb
|
134
133
|
- lib/geocoder/results/maxmind_geoip2.rb
|
135
134
|
- lib/geocoder/results/maxmind_local.rb
|
@@ -142,6 +141,7 @@ files:
|
|
142
141
|
- lib/geocoder/results/postcodes_io.rb
|
143
142
|
- lib/geocoder/results/smarty_streets.rb
|
144
143
|
- lib/geocoder/results/telize.rb
|
144
|
+
- lib/geocoder/results/tencent.rb
|
145
145
|
- lib/geocoder/results/test.rb
|
146
146
|
- lib/geocoder/results/yandex.rb
|
147
147
|
- lib/geocoder/sql.rb
|
@@ -1,15 +0,0 @@
|
|
1
|
-
require 'geocoder/lookups/pelias'
|
2
|
-
require 'geocoder/results/mapzen'
|
3
|
-
|
4
|
-
# https://mapzen.com/documentation/search/search/ for more information
|
5
|
-
module Geocoder::Lookup
|
6
|
-
class Mapzen < Pelias
|
7
|
-
def name
|
8
|
-
'Mapzen'
|
9
|
-
end
|
10
|
-
|
11
|
-
def endpoint
|
12
|
-
configuration[:endpoint] || 'search.mapzen.com'
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|