geocoder 1.7.3 → 1.8.1
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 +22 -0
- data/README.md +5 -6
- data/examples/app_defined_lookup_services.rb +22 -0
- data/lib/generators/geocoder/config/templates/initializer.rb +0 -1
- data/lib/geocoder/cache.rb +2 -2
- data/lib/geocoder/configuration.rb +13 -6
- data/lib/geocoder/lookup.rb +18 -4
- data/lib/geocoder/lookups/amap.rb +2 -2
- data/lib/geocoder/lookups/base.rb +1 -6
- data/lib/geocoder/lookups/freegeoip.rb +8 -6
- data/lib/geocoder/lookups/geoapify.rb +7 -1
- 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 +20 -3
- data/lib/geocoder/lookups/here.rb +25 -20
- data/lib/geocoder/lookups/ipbase.rb +49 -0
- data/lib/geocoder/lookups/location_iq.rb +5 -1
- data/lib/geocoder/lookups/test.rb +1 -0
- data/lib/geocoder/lookups/twogis.rb +58 -0
- data/lib/geocoder/lookups/yandex.rb +3 -3
- data/lib/geocoder/results/here.rb +20 -25
- data/lib/geocoder/results/ipbase.rb +40 -0
- data/lib/geocoder/results/twogis.rb +76 -0
- data/lib/geocoder/version.rb +1 -1
- metadata +8 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 35c6a6d57b8ff3818e9d1b616558a8bbdc3b4b51db2b2c7dadb720eccafd27b4
|
4
|
+
data.tar.gz: 8e8fe1ba7cb9da58131a965d3d85589084f4d5dd70409990f49b89b83923f4e3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0bbf04cc8488a533038783e2d250706fb2d2439de8ea1e5bf4b89950d1dd51d5e9393454540a23cb4e7fbc33b58f54fec1c71c14c98d6fbe8bb8e5caad786989
|
7
|
+
data.tar.gz: 92b8f5933a421b47cdededea9c8e8df8d2ec6f45cb25c8726b343a773b315929529fe821cae08868576ae2e8c5cdbc5fd1782bd2bfc8c56f36afdc1514f52b58
|
data/CHANGELOG.md
CHANGED
@@ -3,6 +3,28 @@ 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.8.1 (2022 Sep 23)
|
7
|
+
-------------------
|
8
|
+
* Add support for IPBase lookup (thanks github.com/jonallured).
|
9
|
+
* Test cleanup (thanks github.com/jonallured).
|
10
|
+
* Prevent errors when existing constant name shadows a lookup class (thanks github.com/avram-twitch).
|
11
|
+
|
12
|
+
1.8.0 (2022 May 17)
|
13
|
+
-------------------
|
14
|
+
* Add support for 2GIS lookup (thanks github.com/ggrikgg).
|
15
|
+
* Change cache configuration structure and add an expiration option. Cache prefix is now set via {cache_options: {prefix: ...}} instead of {cache_prefix: ...}. See README for details.
|
16
|
+
* Add `:fields` parameter for :google_places_details and :google_places_search lookups. If you haven't been requesting specific fields, you may start getting different data (defaults are now the APIs' defaults). See for details: https://github.com/alexreisner/geocoder/pull/1572 (thanks github.com/czlee).
|
17
|
+
* Update :here lookup to use API version 7. Query options are different, API key must be a string (not an array). See API docs at https://developer.here.com/documentation/geocoding-search-api/api-reference-swagger.html (thanks github.com/Pritilender).
|
18
|
+
|
19
|
+
1.7.5 (2022 Mar 14)
|
20
|
+
-------------------
|
21
|
+
* Avoid lookup naming collisions in some environments.
|
22
|
+
|
23
|
+
1.7.4 (2022 Mar 14)
|
24
|
+
-------------------
|
25
|
+
* Add ability to use app-defined lookups (thanks github.com/januszm).
|
26
|
+
* Updates to LocationIQ and FreeGeoIP lookups.
|
27
|
+
|
6
28
|
1.7.3 (2022 Jan 17)
|
7
29
|
-------------------
|
8
30
|
* Get rid of unnecessary cache_prefix deprecation warnings.
|
data/README.md
CHANGED
@@ -20,7 +20,7 @@ Compatibility:
|
|
20
20
|
|
21
21
|
* Ruby versions: 2.1+, and JRuby.
|
22
22
|
* Databases: MySQL, PostgreSQL, SQLite, and MongoDB.
|
23
|
-
* Rails: 5.x and
|
23
|
+
* Rails: 5.x, 6.x, and 7.x.
|
24
24
|
* Works outside of Rails with the `json` (for MRI) or `json_pure` (for JRuby) gem.
|
25
25
|
|
26
26
|
|
@@ -78,7 +78,7 @@ results.first.address
|
|
78
78
|
# => "Hôtel de Ville, 75004 Paris, France"
|
79
79
|
```
|
80
80
|
|
81
|
-
You can also look up the location of an IP
|
81
|
+
You can also look up the location of an IP address:
|
82
82
|
|
83
83
|
```ruby
|
84
84
|
results = Geocoder.search("172.56.21.89")
|
@@ -246,11 +246,10 @@ Geocoder.configure(
|
|
246
246
|
units: :km,
|
247
247
|
|
248
248
|
# caching (see Caching section below for details):
|
249
|
-
# warning: `cache_prefix` is deprecated, use `cache_options` instead
|
250
249
|
cache: Redis.new,
|
251
250
|
cache_options: {
|
252
|
-
expiration:
|
253
|
-
prefix: "
|
251
|
+
expiration: 1.day, # Defaults to `nil`
|
252
|
+
prefix: "another_key:" # Defaults to `geocoder:`
|
254
253
|
}
|
255
254
|
)
|
256
255
|
```
|
@@ -748,7 +747,7 @@ If your application requires quick geocoding responses you will probably need to
|
|
748
747
|
|
749
748
|
For IP address lookups in Rails applications, it is generally NOT a good idea to run `request.location` during a synchronous page load without understanding the speed/behavior of your configured lookup. If the lookup becomes slow, so will your website.
|
750
749
|
|
751
|
-
For the most part, the speed of geocoding requests has little to do with the Geocoder gem. Please take the time to learn about your configured lookup
|
750
|
+
For the most part, the speed of geocoding requests has little to do with the Geocoder gem. Please take the time to learn about your configured lookup before posting performance-related issues.
|
752
751
|
|
753
752
|
### Unexpected Responses from Geocoding Services
|
754
753
|
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# To extend the Geocoder with additional lookups that come from the application,
|
2
|
+
# not shipped with the gem, define a "child" lookup in your application, based on existing one.
|
3
|
+
# This is required because the Geocoder::Configuration is a Singleton and stores one api key per lookup.
|
4
|
+
|
5
|
+
# in app/libs/geocoder/lookup/my_preciousss.rb
|
6
|
+
module Geocoder::Lookup
|
7
|
+
class MyPreciousss < Google
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
# Update Geocoder's street_services on initialize:
|
12
|
+
# config/initializers/geocoder.rb
|
13
|
+
Geocoder::Lookup.street_services << :my_preciousss
|
14
|
+
|
15
|
+
# Override the configuration when necessary (e.g. provide separate Google API key for the account):
|
16
|
+
Geocoder.configure(my_preciousss: { api_key: 'abcdef' })
|
17
|
+
|
18
|
+
# Lastly, search using your custom lookup service/api keys
|
19
|
+
Geocoder.search("Paris", lookup: :my_preciousss)
|
20
|
+
|
21
|
+
# This is useful when we have groups of users in the application who use Google paid services
|
22
|
+
# and we want to properly separate them and allow using individual API KEYS or timeouts.
|
@@ -9,7 +9,6 @@ Geocoder.configure(
|
|
9
9
|
# https_proxy: nil, # HTTPS proxy server (user:pass@host:port)
|
10
10
|
# api_key: nil, # API key for geocoding service
|
11
11
|
# cache: nil, # cache object (must respond to #[], #[]=, and #del)
|
12
|
-
# cache_prefix: 'geocoder:', # DEPRECATED, please use cache_options[:prefix] instead
|
13
12
|
|
14
13
|
# Exceptions that should not be rescued by default
|
15
14
|
# (if you want to implement custom error handling);
|
data/lib/geocoder/cache.rb
CHANGED
@@ -14,7 +14,7 @@ module Geocoder
|
|
14
14
|
def [](url)
|
15
15
|
interpret store_service.read(url)
|
16
16
|
rescue => e
|
17
|
-
warn "Geocoder cache read error: #{e}"
|
17
|
+
Geocoder.log(:warn, "Geocoder cache read error: #{e}")
|
18
18
|
end
|
19
19
|
|
20
20
|
##
|
@@ -23,7 +23,7 @@ module Geocoder
|
|
23
23
|
def []=(url, value)
|
24
24
|
store_service.write(url, value)
|
25
25
|
rescue => e
|
26
|
-
warn "Geocoder cache write error: #{e}"
|
26
|
+
Geocoder.log(:warn, "Geocoder cache write error: #{e}")
|
27
27
|
end
|
28
28
|
|
29
29
|
##
|
@@ -62,7 +62,6 @@ module Geocoder
|
|
62
62
|
:https_proxy,
|
63
63
|
:api_key,
|
64
64
|
:cache,
|
65
|
-
:cache_prefix,
|
66
65
|
:always_raise,
|
67
66
|
:units,
|
68
67
|
:distances,
|
@@ -78,6 +77,10 @@ module Geocoder
|
|
78
77
|
instance.set_defaults
|
79
78
|
end
|
80
79
|
|
80
|
+
def self.initialize
|
81
|
+
instance.send(:initialize)
|
82
|
+
end
|
83
|
+
|
81
84
|
OPTIONS.each do |o|
|
82
85
|
define_method o do
|
83
86
|
@data[o]
|
@@ -108,8 +111,6 @@ module Geocoder
|
|
108
111
|
@data[:http_proxy] = nil # HTTP proxy server (user:pass@host:port)
|
109
112
|
@data[:https_proxy] = nil # HTTPS proxy server (user:pass@host:port)
|
110
113
|
@data[:api_key] = nil # API key for geocoding service
|
111
|
-
@data[:cache] = nil # cache object (must respond to #[], #[]=, and optionally #keys)
|
112
|
-
@data[:cache_prefix] = nil # - DEPRECATED - prefix (string) to use for all cache keys
|
113
114
|
@data[:basic_auth] = {} # user and password for basic auth ({:user => "user", :password => "password"})
|
114
115
|
@data[:logger] = :kernel # :kernel or Logger instance
|
115
116
|
@data[:kernel_logger_level] = ::Logger::WARN # log level, if kernel logger is used
|
@@ -123,9 +124,15 @@ module Geocoder
|
|
123
124
|
@data[:units] = :mi # :mi or :km
|
124
125
|
@data[:distances] = :linear # :linear or :spherical
|
125
126
|
|
126
|
-
#
|
127
|
-
|
128
|
-
|
127
|
+
# Set the default values for the caching mechanism
|
128
|
+
# By default, the cache keys will not expire as IP addresses and phyiscal
|
129
|
+
# addresses will rarely change.
|
130
|
+
@data[:cache] = nil # cache object (must respond to #[], #[]=, and optionally #keys)
|
131
|
+
@data[:cache_prefix] = nil # - DEPRECATED - prefix (string) to use for all cache keys
|
132
|
+
@data[:cache_options] = {
|
133
|
+
prefix: 'geocoder:',
|
134
|
+
expiration: nil
|
135
|
+
}
|
129
136
|
end
|
130
137
|
|
131
138
|
instance_eval(OPTIONS.map do |option|
|
data/lib/geocoder/lookup.rb
CHANGED
@@ -65,7 +65,8 @@ module Geocoder
|
|
65
65
|
:melissa_street,
|
66
66
|
:amazon_location_service,
|
67
67
|
:geoapify,
|
68
|
-
:photon
|
68
|
+
:photon,
|
69
|
+
:twogis
|
69
70
|
]
|
70
71
|
end
|
71
72
|
|
@@ -91,7 +92,8 @@ module Geocoder
|
|
91
92
|
:ipstack,
|
92
93
|
:ip2location,
|
93
94
|
:ipgeolocation,
|
94
|
-
:ipqualityscore
|
95
|
+
:ipqualityscore,
|
96
|
+
:ipbase
|
95
97
|
]
|
96
98
|
end
|
97
99
|
|
@@ -117,8 +119,7 @@ module Geocoder
|
|
117
119
|
def spawn(name)
|
118
120
|
if all_services.include?(name)
|
119
121
|
name = name.to_s
|
120
|
-
|
121
|
-
Geocoder::Lookup.const_get(classify_name(name)).new
|
122
|
+
instantiate_lookup(name)
|
122
123
|
else
|
123
124
|
valids = all_services.map(&:inspect).join(", ")
|
124
125
|
raise ConfigurationError, "Please specify a valid lookup for Geocoder " +
|
@@ -132,5 +133,18 @@ module Geocoder
|
|
132
133
|
def classify_name(filename)
|
133
134
|
filename.to_s.split("_").map{ |i| i[0...1].upcase + i[1..-1] }.join
|
134
135
|
end
|
136
|
+
|
137
|
+
##
|
138
|
+
# Safely instantiate Lookup
|
139
|
+
#
|
140
|
+
def instantiate_lookup(name)
|
141
|
+
class_name = classify_name(name)
|
142
|
+
begin
|
143
|
+
Geocoder::Lookup.const_get(class_name, inherit=false)
|
144
|
+
rescue NameError
|
145
|
+
require "geocoder/lookups/#{name}"
|
146
|
+
end
|
147
|
+
Geocoder::Lookup.const_get(class_name).new
|
148
|
+
end
|
135
149
|
end
|
136
150
|
end
|
@@ -32,10 +32,10 @@ module Geocoder::Lookup
|
|
32
32
|
return doc['geocodes'] unless doc['geocodes'].blank?
|
33
33
|
when ['0', 'INVALID_USER_KEY']
|
34
34
|
raise_error(Geocoder::InvalidApiKey, "invalid api key") ||
|
35
|
-
warn
|
35
|
+
Geocoder.log(:warn, "#{self.name} Geocoding API error: invalid api key.")
|
36
36
|
else
|
37
37
|
raise_error(Geocoder::Error, "server error.") ||
|
38
|
-
warn
|
38
|
+
Geocoder.log(:warn, "#{self.name} Geocoding API error: server error - [#{doc['info']}]")
|
39
39
|
end
|
40
40
|
return []
|
41
41
|
end
|
@@ -83,13 +83,8 @@ module Geocoder
|
|
83
83
|
# The working Cache object.
|
84
84
|
#
|
85
85
|
def cache
|
86
|
-
if @cache.nil?
|
86
|
+
if @cache.nil? and store = configuration.cache
|
87
87
|
cache_options = configuration.cache_options
|
88
|
-
cache_prefix = (configuration.cache_prefix rescue false)
|
89
|
-
if cache_prefix
|
90
|
-
cache_options[:prefix] ||= configuration.cache_prefix
|
91
|
-
warn '[Geocoder] cache_prefix is deprecated, please change to cache_options.prefix instead'
|
92
|
-
end
|
93
88
|
@cache = Cache.new(store, cache_options)
|
94
89
|
end
|
95
90
|
@cache
|
@@ -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)
|
@@ -22,7 +22,13 @@ module Geocoder
|
|
22
22
|
private
|
23
23
|
|
24
24
|
def base_query_url(query)
|
25
|
-
method = query.reverse_geocode?
|
25
|
+
method = if query.reverse_geocode?
|
26
|
+
'reverse'
|
27
|
+
elsif query.options[:autocomplete]
|
28
|
+
'autocomplete'
|
29
|
+
else
|
30
|
+
'search'
|
31
|
+
end
|
26
32
|
"https://api.geoapify.com/v1/geocode/#{method}?"
|
27
33
|
end
|
28
34
|
|
@@ -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,13 +31,19 @@ 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
|
@@ -52,7 +58,18 @@ module Geocoder
|
|
52
58
|
end
|
53
59
|
|
54
60
|
def format_fields(*fields)
|
55
|
-
fields.flatten.
|
61
|
+
flattened = fields.flatten.compact
|
62
|
+
return if flattened.empty?
|
63
|
+
|
64
|
+
flattened.join(',')
|
65
|
+
end
|
66
|
+
|
67
|
+
def locationbias(query)
|
68
|
+
if query.options.has_key?(:locationbias)
|
69
|
+
query.options[:locationbias]
|
70
|
+
else
|
71
|
+
configuration[:locationbias]
|
72
|
+
end
|
56
73
|
end
|
57
74
|
end
|
58
75
|
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
|
@@ -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
|
@@ -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)
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'geocoder/lookups/base'
|
2
|
+
require "geocoder/results/twogis"
|
3
|
+
|
4
|
+
module Geocoder::Lookup
|
5
|
+
class Twogis < Base
|
6
|
+
|
7
|
+
def name
|
8
|
+
"2gis"
|
9
|
+
end
|
10
|
+
|
11
|
+
def required_api_key_parts
|
12
|
+
["key"]
|
13
|
+
end
|
14
|
+
|
15
|
+
def map_link_url(coordinates)
|
16
|
+
"https://2gis.ru/?m=#{coordinates.join(',')}"
|
17
|
+
end
|
18
|
+
|
19
|
+
def supported_protocols
|
20
|
+
[:https]
|
21
|
+
end
|
22
|
+
|
23
|
+
private # ---------------------------------------------------------------
|
24
|
+
|
25
|
+
def base_query_url(query)
|
26
|
+
"#{protocol}://catalog.api.2gis.com/3.0/items/geocode?"
|
27
|
+
end
|
28
|
+
|
29
|
+
def results(query)
|
30
|
+
return [] unless doc = fetch_data(query)
|
31
|
+
if doc['meta'] && doc['meta']['error']
|
32
|
+
Geocoder.log(:warn, "2gis Geocoding API error: #{doc['meta']["code"]} (#{doc['meta']['error']["message"]}).")
|
33
|
+
return []
|
34
|
+
end
|
35
|
+
if doc['result'] && doc = doc['result']['items']
|
36
|
+
return doc.to_a
|
37
|
+
else
|
38
|
+
Geocoder.log(:warn, "2gis Geocoding API error: unexpected response format.")
|
39
|
+
return []
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def query_url_params(query)
|
44
|
+
if query.reverse_geocode?
|
45
|
+
q = query.coordinates.reverse.join(",")
|
46
|
+
else
|
47
|
+
q = query.sanitized_text
|
48
|
+
end
|
49
|
+
params = {
|
50
|
+
:q => q,
|
51
|
+
:lang => "#{query.language || configuration.language}",
|
52
|
+
:key => configuration.api_key,
|
53
|
+
:fields => 'items.street,items.adm_div,items.full_address_name,items.point,items.geometry.centroid'
|
54
|
+
}
|
55
|
+
params.merge(super)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -24,11 +24,11 @@ module Geocoder::Lookup
|
|
24
24
|
|
25
25
|
def results(query)
|
26
26
|
return [] unless doc = fetch_data(query)
|
27
|
-
if
|
28
|
-
if
|
27
|
+
if [400, 403].include? doc['statusCode']
|
28
|
+
if doc['statusCode'] == 403 and doc['message'] == 'Invalid key'
|
29
29
|
raise_error(Geocoder::InvalidApiKey) || Geocoder.log(:warn, "Invalid API key.")
|
30
30
|
else
|
31
|
-
Geocoder.log(:warn, "Yandex Geocoding API error: #{
|
31
|
+
Geocoder.log(:warn, "Yandex Geocoding API error: #{doc['statusCode']} (#{doc['message']}).")
|
32
32
|
end
|
33
33
|
return []
|
34
34
|
end
|
@@ -7,76 +7,71 @@ module Geocoder::Result
|
|
7
7
|
# A string in the given format.
|
8
8
|
#
|
9
9
|
def address(format = :full)
|
10
|
-
address_data[
|
10
|
+
address_data["label"]
|
11
11
|
end
|
12
12
|
|
13
13
|
##
|
14
14
|
# A two-element array: [lat, lon].
|
15
15
|
#
|
16
16
|
def coordinates
|
17
|
-
fail unless d = @data[
|
18
|
-
[d[
|
17
|
+
fail unless d = @data["position"]
|
18
|
+
[d["lat"].to_f, d["lng"].to_f]
|
19
19
|
end
|
20
20
|
|
21
21
|
def route
|
22
|
-
address_data[
|
22
|
+
address_data["street"]
|
23
23
|
end
|
24
24
|
|
25
25
|
def street_number
|
26
|
-
address_data[
|
26
|
+
address_data["houseNumber"]
|
27
27
|
end
|
28
28
|
|
29
29
|
def state
|
30
|
-
|
31
|
-
if v = d.find{|ad| ad['key']=='StateName'}
|
32
|
-
return v['value']
|
33
|
-
end
|
30
|
+
address_data["state"]
|
34
31
|
end
|
35
32
|
|
36
33
|
def province
|
37
|
-
address_data[
|
34
|
+
address_data["county"]
|
38
35
|
end
|
39
36
|
|
40
37
|
def postal_code
|
41
|
-
address_data[
|
38
|
+
address_data["postalCode"]
|
42
39
|
end
|
43
40
|
|
44
41
|
def city
|
45
|
-
address_data[
|
42
|
+
address_data["city"]
|
46
43
|
end
|
47
44
|
|
48
45
|
def state_code
|
49
|
-
address_data[
|
46
|
+
address_data["stateCode"]
|
50
47
|
end
|
51
48
|
|
52
49
|
def province_code
|
53
|
-
address_data[
|
50
|
+
address_data["state"]
|
54
51
|
end
|
55
52
|
|
56
53
|
def country
|
57
|
-
|
58
|
-
if v = d.find{|ad| ad['key']=='CountryName'}
|
59
|
-
return v['value']
|
60
|
-
end
|
54
|
+
address_data["countryName"]
|
61
55
|
end
|
62
56
|
|
63
57
|
def country_code
|
64
|
-
address_data[
|
58
|
+
address_data["countryCode"]
|
65
59
|
end
|
66
60
|
|
67
61
|
def viewport
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
62
|
+
return [] if data["resultType"] == "place"
|
63
|
+
map_view = data["mapView"]
|
64
|
+
south = map_view["south"]
|
65
|
+
west = map_view["west"]
|
66
|
+
north = map_view["north"]
|
67
|
+
east = map_view["east"]
|
73
68
|
[south, west, north, east]
|
74
69
|
end
|
75
70
|
|
76
71
|
private # ----------------------------------------------------------------
|
77
72
|
|
78
73
|
def address_data
|
79
|
-
@data[
|
74
|
+
@data["address"] || fail
|
80
75
|
end
|
81
76
|
end
|
82
77
|
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'geocoder/results/base'
|
2
|
+
|
3
|
+
module Geocoder::Result
|
4
|
+
class Ipbase < Base
|
5
|
+
def ip
|
6
|
+
@data["data"]['ip']
|
7
|
+
end
|
8
|
+
|
9
|
+
def country_code
|
10
|
+
@data["data"]["location"]["country"]["alpha2"]
|
11
|
+
end
|
12
|
+
|
13
|
+
def country
|
14
|
+
@data["data"]["location"]["country"]["name"]
|
15
|
+
end
|
16
|
+
|
17
|
+
def state_code
|
18
|
+
@data["data"]["location"]["region"]["alpha2"]
|
19
|
+
end
|
20
|
+
|
21
|
+
def state
|
22
|
+
@data["data"]["location"]["region"]["name"]
|
23
|
+
end
|
24
|
+
|
25
|
+
def city
|
26
|
+
@data["data"]["location"]["city"]["name"]
|
27
|
+
end
|
28
|
+
|
29
|
+
def postal_code
|
30
|
+
@data["data"]["location"]["zip"]
|
31
|
+
end
|
32
|
+
|
33
|
+
def coordinates
|
34
|
+
[
|
35
|
+
@data["data"]["location"]["latitude"].to_f,
|
36
|
+
@data["data"]["location"]["longitude"].to_f
|
37
|
+
]
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'geocoder/results/base'
|
2
|
+
|
3
|
+
module Geocoder::Result
|
4
|
+
class Twogis < Base
|
5
|
+
def coordinates
|
6
|
+
['lat', 'lon'].map{ |i| @data['point'][i] } if @data['point']
|
7
|
+
end
|
8
|
+
|
9
|
+
def address(_format = :full)
|
10
|
+
@data['full_address_name'] || ''
|
11
|
+
end
|
12
|
+
|
13
|
+
def city
|
14
|
+
return '' unless @data['adm_div']
|
15
|
+
@data['adm_div'].select{|u| u["type"] == "city"}.first.try(:[], 'name') || ''
|
16
|
+
end
|
17
|
+
|
18
|
+
def region
|
19
|
+
return '' unless @data['adm_div']
|
20
|
+
@data['adm_div'].select{|u| u["type"] == "region"}.first.try(:[], 'name') || ''
|
21
|
+
end
|
22
|
+
|
23
|
+
def country
|
24
|
+
return '' unless @data['adm_div']
|
25
|
+
@data['adm_div'].select{|u| u["type"] == "country"}.first.try(:[], 'name') || ''
|
26
|
+
end
|
27
|
+
|
28
|
+
def district
|
29
|
+
return '' unless @data['adm_div']
|
30
|
+
@data['adm_div'].select{|u| u["type"] == "district"}.first.try(:[], 'name') || ''
|
31
|
+
end
|
32
|
+
|
33
|
+
def district_area
|
34
|
+
return '' unless @data['adm_div']
|
35
|
+
@data['adm_div'].select{|u| u["type"] == "district_area"}.first.try(:[], 'name') || ''
|
36
|
+
end
|
37
|
+
|
38
|
+
def street_address
|
39
|
+
@data['address_name'] || ''
|
40
|
+
end
|
41
|
+
|
42
|
+
def street
|
43
|
+
return '' unless @data['address_name']
|
44
|
+
@data['address_name'].split(', ').first
|
45
|
+
end
|
46
|
+
|
47
|
+
def street_number
|
48
|
+
return '' unless @data['address_name']
|
49
|
+
@data['address_name'].split(', ')[1] || ''
|
50
|
+
end
|
51
|
+
|
52
|
+
def type
|
53
|
+
@data['type'] || ''
|
54
|
+
end
|
55
|
+
|
56
|
+
def purpose_name
|
57
|
+
@data['purpose_name'] || ''
|
58
|
+
end
|
59
|
+
|
60
|
+
def building_name
|
61
|
+
@data['building_name'] || ''
|
62
|
+
end
|
63
|
+
|
64
|
+
def subtype
|
65
|
+
@data['subtype'] || ''
|
66
|
+
end
|
67
|
+
|
68
|
+
def subtype_specification
|
69
|
+
@data['subtype_specification'] || ''
|
70
|
+
end
|
71
|
+
|
72
|
+
def name
|
73
|
+
@data['name'] || ''
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
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.
|
4
|
+
version: 1.8.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: 2022-
|
11
|
+
date: 2022-09-23 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Object geocoding (by street or IP address), reverse geocoding (coordinates
|
14
14
|
to street address), distance queries for ActiveRecord and Mongoid, result caching,
|
@@ -25,6 +25,7 @@ files:
|
|
25
25
|
- README.md
|
26
26
|
- bin/console
|
27
27
|
- bin/geocode
|
28
|
+
- examples/app_defined_lookup_services.rb
|
28
29
|
- examples/cache_bypass.rb
|
29
30
|
- examples/reverse_geocode_job.rb
|
30
31
|
- lib/easting_northing.rb
|
@@ -74,6 +75,7 @@ files:
|
|
74
75
|
- lib/geocoder/lookups/here.rb
|
75
76
|
- lib/geocoder/lookups/ip2location.rb
|
76
77
|
- lib/geocoder/lookups/ipapi_com.rb
|
78
|
+
- lib/geocoder/lookups/ipbase.rb
|
77
79
|
- lib/geocoder/lookups/ipdata_co.rb
|
78
80
|
- lib/geocoder/lookups/ipgeolocation.rb
|
79
81
|
- lib/geocoder/lookups/ipinfo_io.rb
|
@@ -102,6 +104,7 @@ files:
|
|
102
104
|
- lib/geocoder/lookups/telize.rb
|
103
105
|
- lib/geocoder/lookups/tencent.rb
|
104
106
|
- lib/geocoder/lookups/test.rb
|
107
|
+
- lib/geocoder/lookups/twogis.rb
|
105
108
|
- lib/geocoder/lookups/uk_ordnance_survey_names.rb
|
106
109
|
- lib/geocoder/lookups/yandex.rb
|
107
110
|
- lib/geocoder/models/active_record.rb
|
@@ -136,6 +139,7 @@ files:
|
|
136
139
|
- lib/geocoder/results/here.rb
|
137
140
|
- lib/geocoder/results/ip2location.rb
|
138
141
|
- lib/geocoder/results/ipapi_com.rb
|
142
|
+
- lib/geocoder/results/ipbase.rb
|
139
143
|
- lib/geocoder/results/ipdata_co.rb
|
140
144
|
- lib/geocoder/results/ipgeolocation.rb
|
141
145
|
- lib/geocoder/results/ipinfo_io.rb
|
@@ -164,6 +168,7 @@ files:
|
|
164
168
|
- lib/geocoder/results/telize.rb
|
165
169
|
- lib/geocoder/results/tencent.rb
|
166
170
|
- lib/geocoder/results/test.rb
|
171
|
+
- lib/geocoder/results/twogis.rb
|
167
172
|
- lib/geocoder/results/uk_ordnance_survey_names.rb
|
168
173
|
- lib/geocoder/results/yandex.rb
|
169
174
|
- lib/geocoder/sql.rb
|
@@ -198,7 +203,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
198
203
|
- !ruby/object:Gem::Version
|
199
204
|
version: '0'
|
200
205
|
requirements: []
|
201
|
-
rubygems_version: 3.1.
|
206
|
+
rubygems_version: 3.1.6
|
202
207
|
signing_key:
|
203
208
|
specification_version: 4
|
204
209
|
summary: Complete geocoding solution for Ruby.
|