geocoder 1.8.1 → 1.8.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +11 -0
- data/README.md +30 -6
- data/lib/geocoder/cache.rb +1 -1
- data/lib/geocoder/ip_address.rb +5 -2
- data/lib/geocoder/lookup.rb +7 -4
- data/lib/geocoder/lookups/amazon_location_service.rb +5 -4
- data/lib/geocoder/lookups/ban_data_gouv_fr.rb +1 -1
- data/lib/geocoder/lookups/esri.rb +18 -5
- data/lib/geocoder/lookups/google_places_search.rb +1 -2
- data/lib/geocoder/lookups/ip2location_io.rb +62 -0
- data/lib/geocoder/lookups/ip2location_lite.rb +40 -0
- data/lib/geocoder/lookups/pc_miler.rb +85 -0
- data/lib/geocoder/lookups/pdok_nl.rb +43 -0
- data/lib/geocoder/results/amazon_location_service.rb +6 -1
- data/lib/geocoder/results/ban_data_gouv_fr.rb +1 -1
- data/lib/geocoder/results/ip2location_io.rb +21 -0
- data/lib/geocoder/results/ip2location_lite.rb +47 -0
- data/lib/geocoder/results/pc_miler.rb +98 -0
- data/lib/geocoder/results/pdok_nl.rb +62 -0
- data/lib/geocoder/version.rb +1 -1
- data/lib/maxmind_database.rb +12 -12
- data/lib/tasks/maxmind.rake +1 -1
- metadata +43 -9
- data/lib/geocoder/lookups/dstk.rb +0 -22
- data/lib/geocoder/results/dstk.rb +0 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 447dfedeffcb5c111f6441badccf6d1c25c38a3a0fed32aaeb31151d27425a3d
|
4
|
+
data.tar.gz: 89b7f5b123d125ccb329d66f0172ef0a46d3176d6e215cc1a884b0a2249ae4cd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a90b21dfcc3aeb50ac94fad6eafeec0141ba320bb638912b2e0091f80beb30b306f58cc104db8a55ab47cf8a5543edbabe9372dbda7c63dcbeb560c42b92a957
|
7
|
+
data.tar.gz: c0489e8f2b3c4d98cf40235e2b60fc5c8d129cd74aecc65f57bfd9adee7549db804fb0bcdf6b68c14933478fd3a0ea06124350208987a575c916a0992c28adb7
|
data/CHANGELOG.md
CHANGED
@@ -3,6 +3,17 @@ 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.3 (2024 May 2)
|
7
|
+
-------------------
|
8
|
+
* Add support for IP2Location LITE lookup (thanks github.com/ip2location).
|
9
|
+
* Add support for PDOK NL lookup (thanks github.com/opensourceame).
|
10
|
+
* Remove support for Data Science Toolkit lookup (defunct).
|
11
|
+
|
12
|
+
1.8.2 (2023 Jul 4)
|
13
|
+
-------------------
|
14
|
+
* Add support for PC Miler lookup (thanks github.com/alexdean).
|
15
|
+
* Minor fixes for :maxmind_local, :esri, and :ban_data_gouv_fr lookups.
|
16
|
+
|
6
17
|
1.8.1 (2022 Sep 23)
|
7
18
|
-------------------
|
8
19
|
* Add support for IPBase lookup (thanks github.com/jonallured).
|
data/README.md
CHANGED
@@ -5,7 +5,6 @@ Geocoder
|
|
5
5
|
|
6
6
|
[![Gem Version](https://badge.fury.io/rb/geocoder.svg)](http://badge.fury.io/rb/geocoder)
|
7
7
|
[![Code Climate](https://codeclimate.com/github/alexreisner/geocoder/badges/gpa.svg)](https://codeclimate.com/github/alexreisner/geocoder)
|
8
|
-
[![Build Status](https://travis-ci.com/alexreisner/geocoder.svg?branch=master)](https://travis-ci.com/alexreisner/geocoder)
|
9
8
|
|
10
9
|
Key features:
|
11
10
|
|
@@ -368,7 +367,7 @@ If you need to expire cached content:
|
|
368
367
|
```ruby
|
369
368
|
Geocoder::Lookup.get(Geocoder.config[:lookup]).cache.expire(:all) # expire cached results for current Lookup
|
370
369
|
Geocoder::Lookup.get(:nominatim).cache.expire("http://...") # expire cached result for a specific URL
|
371
|
-
Geocoder::Lookup.get(:nominatim).cache.expire(:all) # expire cached results for
|
370
|
+
Geocoder::Lookup.get(:nominatim).cache.expire(:all) # expire cached results for Nominatim
|
372
371
|
# expire all cached results for all Lookups.
|
373
372
|
# Be aware that this methods spawns a new Lookup object for each Service
|
374
373
|
Geocoder::Lookup.all_services.each{|service| Geocoder::Lookup.get(service).cache.expire(:all)}
|
@@ -376,10 +375,9 @@ Geocoder::Lookup.all_services.each{|service| Geocoder::Lookup.get(service).cache
|
|
376
375
|
|
377
376
|
Do *not* include the prefix when passing a URL to be expired. Expiring `:all` will only expire keys with the configured prefix -- it will *not* expire every entry in your key/value store.
|
378
377
|
|
379
|
-
For an example of a cache store with URL expiry, please see examples/autoexpire_cache.rb
|
380
|
-
|
381
378
|
_Before you implement caching in your app please be sure that doing so does not violate the Terms of Service for your geocoding service._
|
382
379
|
|
380
|
+
Not all services support caching, [check the service limitations in the API guide for more information](https://github.com/alexreisner/geocoder/blob/master/README_API_GUIDE.md).
|
383
381
|
|
384
382
|
Advanced Model Configuration
|
385
383
|
----------------------------
|
@@ -736,8 +734,34 @@ you should check your Gemfile to make sure the Mongoid gem is listed _before_ Ge
|
|
736
734
|
|
737
735
|
A lot of debugging time can be saved by understanding how Geocoder works with ActiveRecord. When you use the `near` scope or the `nearbys` method of a geocoded object, Geocoder creates an ActiveModel::Relation object which adds some attributes (eg: distance, bearing) to the SELECT clause. It also adds a condition to the WHERE clause to check that distance is within the given radius. Because the SELECT clause is modified, anything else that modifies the SELECT clause may produce strange results, for example:
|
738
736
|
|
739
|
-
* using
|
740
|
-
*
|
737
|
+
* using [`select` method (selects one or more columns)](https://api.rubyonrails.org/classes/ActiveRecord/QueryMethods.html#method-i-select)
|
738
|
+
* using the [`pluck` method (gets an array with selecting one or more columns)](https://api.rubyonrails.org/classes/ActiveRecord/Calculations.html#method-i-pluck)
|
739
|
+
* The same problem will appear with [ActiveRecord's `ids` method](https://api.rubyonrails.org/classes/ActiveRecord/Calculations.html#method-i-ids).
|
740
|
+
* specifying another model through [`includes` (selects columns from other tables)](https://api.rubyonrails.org/classes/ActiveRecord/QueryMethods.html#method-i-includes)
|
741
|
+
* See also Known Issues [using-near-with-includes](#using-near-with-select) section.
|
742
|
+
|
743
|
+
If you get an error in the above cases, try the following:
|
744
|
+
|
745
|
+
```ruby
|
746
|
+
# Use the :select option with the near scope to get the columns you want.
|
747
|
+
# Instead of City.near(...).select(:id, :name), try:
|
748
|
+
City.near("Omaha, NE", 20, select: "id, name")
|
749
|
+
|
750
|
+
# Pass a :select option to the near scope to get the columns you want.
|
751
|
+
# Then, Ruby's built-in pluck method gets arrays you want.
|
752
|
+
# Instead of City.near(...).pluck(:id) or City.near(...).ids,, try:
|
753
|
+
City.near("Omaha, NE", 20, select: "id, name").to_a.pluck(:id, :name)
|
754
|
+
City.near("Omaha, NE", 20, select: "id").to_a.pluck(:id)
|
755
|
+
|
756
|
+
# Pass a :select option to the near scope to get the columns you want.
|
757
|
+
# Instead of City.near(...).includes(:venues), try:
|
758
|
+
City.near("Omaha, NE", 20, select: "cities.*, venues.*").joins(:venues)
|
759
|
+
|
760
|
+
# This preload call will normally trigger two queries regardless of the
|
761
|
+
# number of results; one query on hotels, and one query on administrators.
|
762
|
+
# Instead of Hotel.near(...).includes(:administrator), try:
|
763
|
+
Hotel.near("London, UK", 50).joins(:administrator).preload(:administrator)
|
764
|
+
```
|
741
765
|
|
742
766
|
### Geocoding is Slow
|
743
767
|
|
data/lib/geocoder/cache.rb
CHANGED
@@ -4,7 +4,7 @@ module Geocoder
|
|
4
4
|
class Cache
|
5
5
|
|
6
6
|
def initialize(store, config)
|
7
|
-
@class = (
|
7
|
+
@class = (Geocoder::CacheStore.const_get("#{store.class}", false) rescue Geocoder::CacheStore::Generic)
|
8
8
|
@store_service = @class.new(store, config)
|
9
9
|
end
|
10
10
|
|
data/lib/geocoder/ip_address.rb
CHANGED
data/lib/geocoder/lookup.rb
CHANGED
@@ -23,7 +23,7 @@ module Geocoder
|
|
23
23
|
# For example, Amazon Location Service uses the AWS gem, not HTTP REST requests, to fetch data.
|
24
24
|
#
|
25
25
|
def all_services_with_http_requests
|
26
|
-
all_services_except_test - [:amazon_location_service]
|
26
|
+
all_services_except_test - [:amazon_location_service, :maxmind_local, :geoip2, :ip2location_lite]
|
27
27
|
end
|
28
28
|
|
29
29
|
##
|
@@ -32,7 +32,6 @@ module Geocoder
|
|
32
32
|
def street_services
|
33
33
|
@street_services ||= [
|
34
34
|
:location_iq,
|
35
|
-
:dstk,
|
36
35
|
:esri,
|
37
36
|
:google,
|
38
37
|
:google_premier,
|
@@ -48,6 +47,7 @@ module Geocoder
|
|
48
47
|
:uk_ordnance_survey_names,
|
49
48
|
:opencagedata,
|
50
49
|
:pelias,
|
50
|
+
:pdok_nl,
|
51
51
|
:pickpoint,
|
52
52
|
:here,
|
53
53
|
:baidu,
|
@@ -66,7 +66,8 @@ module Geocoder
|
|
66
66
|
:amazon_location_service,
|
67
67
|
:geoapify,
|
68
68
|
:photon,
|
69
|
-
:twogis
|
69
|
+
:twogis,
|
70
|
+
:pc_miler
|
70
71
|
]
|
71
72
|
end
|
72
73
|
|
@@ -93,7 +94,9 @@ module Geocoder
|
|
93
94
|
:ip2location,
|
94
95
|
:ipgeolocation,
|
95
96
|
:ipqualityscore,
|
96
|
-
:ipbase
|
97
|
+
:ipbase,
|
98
|
+
:ip2location_io,
|
99
|
+
:ip2location_lite
|
97
100
|
]
|
98
101
|
end
|
99
102
|
|
@@ -19,7 +19,7 @@ module Geocoder::Lookup
|
|
19
19
|
client.search_place_index_for_text(params.merge(text: query.text))
|
20
20
|
end
|
21
21
|
|
22
|
-
resp.results
|
22
|
+
resp.results
|
23
23
|
end
|
24
24
|
|
25
25
|
private
|
@@ -29,10 +29,11 @@ module Geocoder::Lookup
|
|
29
29
|
require_sdk
|
30
30
|
keys = configuration.api_key
|
31
31
|
if keys
|
32
|
-
@client = Aws::LocationService::Client.new(
|
32
|
+
@client = Aws::LocationService::Client.new(**{
|
33
|
+
region: keys[:region],
|
33
34
|
access_key_id: keys[:access_key_id],
|
34
|
-
secret_access_key: keys[:secret_access_key]
|
35
|
-
)
|
35
|
+
secret_access_key: keys[:secret_access_key]
|
36
|
+
}.compact)
|
36
37
|
else
|
37
38
|
@client = Aws::LocationService::Client.new
|
38
39
|
end
|
@@ -125,7 +125,7 @@ module Geocoder::Lookup
|
|
125
125
|
end
|
126
126
|
|
127
127
|
def type_param_is_valid?(param)
|
128
|
-
%w(housenumber street locality
|
128
|
+
%w(housenumber street locality municipality).include?(param.downcase)
|
129
129
|
end
|
130
130
|
|
131
131
|
def code_param_is_valid?(param)
|
@@ -23,15 +23,28 @@ module Geocoder::Lookup
|
|
23
23
|
def results(query)
|
24
24
|
return [] unless doc = fetch_data(query)
|
25
25
|
|
26
|
-
if (!query.reverse_geocode?)
|
27
|
-
return [] if !doc['locations'] || doc['locations'].empty?
|
28
|
-
end
|
29
|
-
|
30
26
|
if (doc['error'].nil?)
|
27
|
+
if (!query.reverse_geocode?)
|
28
|
+
return [] if !doc['locations'] || doc['locations'].empty?
|
29
|
+
end
|
31
30
|
return [ doc ]
|
32
31
|
else
|
33
|
-
|
32
|
+
case [ doc['error']['code'] ]
|
33
|
+
when [498]
|
34
|
+
raise_error(Geocoder::InvalidApiKey, doc['error']['message']) ||
|
35
|
+
Geocoder.log(:warn, "#{self.name} Geocoding API error: #{doc['error']['message']}")
|
36
|
+
when [ 403 ]
|
37
|
+
raise_error(Geocoder::RequestDenied, 'ESRI request denied') ||
|
38
|
+
Geocoder.log(:warn, "#{self.name} ESRI request denied: #{doc['error']['message']}")
|
39
|
+
when [ 500 ], [501]
|
40
|
+
raise_error(Geocoder::ServiceUnavailable, 'ESRI service unavailable') ||
|
41
|
+
Geocoder.log(:warn, "#{self.name} ESRI service error: #{doc['error']['message']}")
|
42
|
+
else
|
43
|
+
raise_error(Geocoder::Error, doc['error']['message']) ||
|
44
|
+
Geocoder.log(:warn, "#{self.name} Geocoding error: #{doc['error']['message']}")
|
45
|
+
end
|
34
46
|
end
|
47
|
+
return []
|
35
48
|
end
|
36
49
|
|
37
50
|
def query_url_params(query)
|
@@ -49,12 +49,11 @@ module Geocoder
|
|
49
49
|
end
|
50
50
|
|
51
51
|
def default_fields
|
52
|
-
legacy = %w[id reference]
|
53
52
|
basic = %w[business_status formatted_address geometry icon name
|
54
53
|
photos place_id plus_code types]
|
55
54
|
contact = %w[opening_hours]
|
56
55
|
atmosphere = %W[price_level rating user_ratings_total]
|
57
|
-
format_fields(
|
56
|
+
format_fields(basic, contact, atmosphere)
|
58
57
|
end
|
59
58
|
|
60
59
|
def format_fields(*fields)
|
@@ -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,85 @@
|
|
1
|
+
require 'geocoder/lookups/base'
|
2
|
+
require "geocoder/results/pc_miler"
|
3
|
+
require 'cgi' unless defined?(CGI) && defined?(CGI.escape)
|
4
|
+
|
5
|
+
module Geocoder::Lookup
|
6
|
+
class PcMiler < Base
|
7
|
+
|
8
|
+
# https://developer.trimblemaps.com/restful-apis/location/single-search/single-search-api/#test-the-api-now
|
9
|
+
def valid_region_codes
|
10
|
+
# AF: Africa
|
11
|
+
# AS: Asia
|
12
|
+
# EU: Europe
|
13
|
+
# NA: North America
|
14
|
+
# OC: Oceania
|
15
|
+
# SA: South America
|
16
|
+
%w[AF AS EU NA OC SA]
|
17
|
+
end
|
18
|
+
|
19
|
+
def name
|
20
|
+
"PCMiler"
|
21
|
+
end
|
22
|
+
|
23
|
+
private # ---------------------------------------------------------------
|
24
|
+
|
25
|
+
def base_query_url(query)
|
26
|
+
region_code = region(query)
|
27
|
+
if !valid_region_codes.include?(region_code)
|
28
|
+
raise "region_code '#{region_code}' is invalid. use one of #{valid_region_codes}." \
|
29
|
+
"https://developer.trimblemaps.com/restful-apis/location/single-search/single-search-api/#test-the-api-now"
|
30
|
+
end
|
31
|
+
|
32
|
+
"#{protocol}://singlesearch.alk.com/#{region_code}/api/search?"
|
33
|
+
end
|
34
|
+
|
35
|
+
def results(query)
|
36
|
+
return [] unless data = fetch_data(query)
|
37
|
+
if data['Locations']
|
38
|
+
add_metadata_to_locations!(data)
|
39
|
+
data['Locations']
|
40
|
+
else
|
41
|
+
[]
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def add_metadata_to_locations!(data)
|
46
|
+
confidence = data['QueryConfidence']
|
47
|
+
data['Locations'].each do |location|
|
48
|
+
location['QueryConfidence'] = confidence
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def query_url_params(query)
|
53
|
+
if query.reverse_geocode?
|
54
|
+
lat,lon = query.coordinates
|
55
|
+
formatted_query = "#{CGI.escape(lat)},#{CGI.escape(lon)}"
|
56
|
+
else
|
57
|
+
formatted_query = query.text.to_s
|
58
|
+
end
|
59
|
+
|
60
|
+
{
|
61
|
+
authToken: configuration.api_key,
|
62
|
+
query: formatted_query,
|
63
|
+
# to add additional metadata to response such as QueryConfidence
|
64
|
+
include: 'Meta'
|
65
|
+
}.merge(super(query))
|
66
|
+
end
|
67
|
+
|
68
|
+
def region(query)
|
69
|
+
query.options[:region] || query.options['region'] || configuration[:region] || "NA"
|
70
|
+
end
|
71
|
+
|
72
|
+
def check_response_for_errors!(response)
|
73
|
+
if response.code.to_i == 403
|
74
|
+
raise_error(Geocoder::RequestDenied) ||
|
75
|
+
Geocoder.log(:warn, "Geocoding API error: 403 API key does not exist")
|
76
|
+
else
|
77
|
+
super(response)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def supported_protocols
|
82
|
+
[:https]
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'geocoder/lookups/base'
|
2
|
+
require "geocoder/results/pdok_nl"
|
3
|
+
|
4
|
+
module Geocoder::Lookup
|
5
|
+
class PdokNl < Base
|
6
|
+
|
7
|
+
def name
|
8
|
+
'pdok NL'
|
9
|
+
end
|
10
|
+
|
11
|
+
def supported_protocols
|
12
|
+
[:https]
|
13
|
+
end
|
14
|
+
|
15
|
+
private # ---------------------------------------------------------------
|
16
|
+
|
17
|
+
def cache_key(query)
|
18
|
+
base_query_url(query) + hash_to_query(query_url_params(query))
|
19
|
+
end
|
20
|
+
|
21
|
+
def base_query_url(query)
|
22
|
+
"#{protocol}://api.pdok.nl/bzk/locatieserver/search/v3_1/free?"
|
23
|
+
end
|
24
|
+
|
25
|
+
def valid_response?(response)
|
26
|
+
json = parse_json(response.body)
|
27
|
+
super(response) if json
|
28
|
+
end
|
29
|
+
|
30
|
+
def results(query)
|
31
|
+
return [] unless doc = fetch_data(query)
|
32
|
+
return doc['response']['docs']
|
33
|
+
end
|
34
|
+
|
35
|
+
def query_url_params(query)
|
36
|
+
{
|
37
|
+
fl: '*',
|
38
|
+
q: query.text,
|
39
|
+
wt: 'json'
|
40
|
+
}.merge(super)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -3,7 +3,8 @@ require 'geocoder/results/base'
|
|
3
3
|
module Geocoder::Result
|
4
4
|
class AmazonLocationService < Base
|
5
5
|
def initialize(result)
|
6
|
-
@place = result
|
6
|
+
@place = result.place
|
7
|
+
super
|
7
8
|
end
|
8
9
|
|
9
10
|
def coordinates
|
@@ -53,5 +54,9 @@ module Geocoder::Result
|
|
53
54
|
def country_code
|
54
55
|
@place.country
|
55
56
|
end
|
57
|
+
|
58
|
+
def place_id
|
59
|
+
data.place_id if data.respond_to?(:place_id)
|
60
|
+
end
|
56
61
|
end
|
57
62
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'geocoder/results/base'
|
2
|
+
|
3
|
+
module Geocoder::Result
|
4
|
+
class Ip2locationIo < Base
|
5
|
+
|
6
|
+
def address(format = :full)
|
7
|
+
"#{city_name} #{zip_code}, #{country_name}".sub(/^[ ,]*/, '')
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.response_attributes
|
11
|
+
%w[ip country_code country_name region_name city_name latitude longitude
|
12
|
+
zip_code time_zone asn as is_proxy]
|
13
|
+
end
|
14
|
+
|
15
|
+
response_attributes.each do |attr|
|
16
|
+
define_method attr do
|
17
|
+
@data[attr] || ""
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'geocoder/results/base'
|
2
|
+
|
3
|
+
module Geocoder::Result
|
4
|
+
class Ip2locationLite < Base
|
5
|
+
|
6
|
+
def coordinates
|
7
|
+
[@data[:latitude], @data[:longitude]]
|
8
|
+
end
|
9
|
+
|
10
|
+
def city
|
11
|
+
@data[:city]
|
12
|
+
end
|
13
|
+
|
14
|
+
def state
|
15
|
+
@data[:region]
|
16
|
+
end
|
17
|
+
|
18
|
+
def state_code
|
19
|
+
"" # Not available in Maxmind's database
|
20
|
+
end
|
21
|
+
|
22
|
+
def country
|
23
|
+
@data[:country_long]
|
24
|
+
end
|
25
|
+
|
26
|
+
def country_code
|
27
|
+
@data[:country_short]
|
28
|
+
end
|
29
|
+
|
30
|
+
def postal_code
|
31
|
+
@data[:zipcode]
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.response_attributes
|
35
|
+
%w[country_short country_long region latitude longitude isp
|
36
|
+
domain netspeed areacode iddcode timezone zipcode weatherstationname
|
37
|
+
weatherstationcode mcc mnc mobilebrand elevation usagetype addresstype
|
38
|
+
category district asn as]
|
39
|
+
end
|
40
|
+
|
41
|
+
response_attributes.each do |a|
|
42
|
+
define_method a do
|
43
|
+
@data[a] || ""
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
require 'geocoder/results/base'
|
2
|
+
|
3
|
+
module Geocoder::Result
|
4
|
+
class PcMiler < Base
|
5
|
+
# sample response:
|
6
|
+
# https://singlesearch.alk.com/na/api/search?authToken=<TOKEN>&include=Meta&query=Feasterville
|
7
|
+
#
|
8
|
+
# {
|
9
|
+
# "Err": 0,
|
10
|
+
# "ErrString": "OK",
|
11
|
+
# "QueryConfidence": 1,
|
12
|
+
# "TimeInMilliseconds": 93,
|
13
|
+
# "GridDataVersion": "GRD_ALK.NA.2023.01.18.29.1.1",
|
14
|
+
# "CommitID": "pcmws-22.08.11.0-1778-g586da49bd1b: 05/30/2023 20:14",
|
15
|
+
# "Locations": [
|
16
|
+
# {
|
17
|
+
# "Address": {
|
18
|
+
# "StreetAddress": "",
|
19
|
+
# "LocalArea": "",
|
20
|
+
# "City": "Feasterville",
|
21
|
+
# "State": "PA",
|
22
|
+
# "StateName": "Pennsylvania",
|
23
|
+
# "Zip": "19053",
|
24
|
+
# "County": "Bucks",
|
25
|
+
# "Country": "US",
|
26
|
+
# "CountryFullName": "United States",
|
27
|
+
# "SPLC": null
|
28
|
+
# },
|
29
|
+
# "Coords": {
|
30
|
+
# "Lat": "40.150025",
|
31
|
+
# "Lon": "-75.002511"
|
32
|
+
# },
|
33
|
+
# "StreetCoords": {
|
34
|
+
# "Lat": "40.150098",
|
35
|
+
# "Lon": "-75.002827"
|
36
|
+
# },
|
37
|
+
# "Region": 4,
|
38
|
+
# "POITypeID": 0,
|
39
|
+
# "PersistentPOIID": -1,
|
40
|
+
# "SiteID": -1,
|
41
|
+
# "ResultType": 4,
|
42
|
+
# "ShortString": "Feasterville",
|
43
|
+
# "GridID": 37172748,
|
44
|
+
# "LinkID": 188,
|
45
|
+
# "Percent": 6291,
|
46
|
+
# "TimeZone": "GMT-4:00 EDT"
|
47
|
+
# }
|
48
|
+
# ]
|
49
|
+
# }
|
50
|
+
|
51
|
+
def address(format=:unused)
|
52
|
+
[street, city, state, postal_code, country]
|
53
|
+
.map { |i| i == '' ? nil : i }
|
54
|
+
.compact
|
55
|
+
.join(', ')
|
56
|
+
end
|
57
|
+
|
58
|
+
def coordinates
|
59
|
+
coords = data["Coords"] || {}
|
60
|
+
[coords["Lat"].to_f, coords["Lon"].to_f]
|
61
|
+
end
|
62
|
+
|
63
|
+
def street
|
64
|
+
address_data["StreetAddress"]
|
65
|
+
end
|
66
|
+
|
67
|
+
def city
|
68
|
+
address_data["City"]
|
69
|
+
end
|
70
|
+
|
71
|
+
def state
|
72
|
+
address_data["StateName"]
|
73
|
+
end
|
74
|
+
|
75
|
+
def state_code
|
76
|
+
address_data["State"]
|
77
|
+
end
|
78
|
+
|
79
|
+
def postal_code
|
80
|
+
address_data["Zip"]
|
81
|
+
end
|
82
|
+
|
83
|
+
def country
|
84
|
+
address_data["CountryFullName"]
|
85
|
+
end
|
86
|
+
|
87
|
+
def country_code
|
88
|
+
address_data["Country"]
|
89
|
+
end
|
90
|
+
|
91
|
+
private
|
92
|
+
|
93
|
+
def address_data
|
94
|
+
data["Address"] || {}
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'geocoder/results/base'
|
2
|
+
|
3
|
+
module Geocoder::Result
|
4
|
+
class PdokNl < Base
|
5
|
+
|
6
|
+
def response_attributes
|
7
|
+
@data
|
8
|
+
end
|
9
|
+
|
10
|
+
def coordinates
|
11
|
+
@data['centroide_ll'][6..-2].split(' ').map(&:to_f).reverse
|
12
|
+
end
|
13
|
+
|
14
|
+
def formatted_address
|
15
|
+
@data['weergavenaam']
|
16
|
+
end
|
17
|
+
|
18
|
+
alias_method :address, :formatted_address
|
19
|
+
|
20
|
+
def province
|
21
|
+
@data['provincienaam']
|
22
|
+
end
|
23
|
+
|
24
|
+
alias_method :state, :province
|
25
|
+
|
26
|
+
def city
|
27
|
+
@data['woonplaatsnaam']
|
28
|
+
end
|
29
|
+
|
30
|
+
def district
|
31
|
+
@data['gemeentenaam']
|
32
|
+
end
|
33
|
+
|
34
|
+
def street
|
35
|
+
@data['straatnaam']
|
36
|
+
end
|
37
|
+
|
38
|
+
def street_number
|
39
|
+
@data['huis_nlt']
|
40
|
+
end
|
41
|
+
|
42
|
+
def address_components
|
43
|
+
@data
|
44
|
+
end
|
45
|
+
|
46
|
+
def state_code
|
47
|
+
@data['provinciecode']
|
48
|
+
end
|
49
|
+
|
50
|
+
def postal_code
|
51
|
+
@data['postcode']
|
52
|
+
end
|
53
|
+
|
54
|
+
def country
|
55
|
+
"Netherlands"
|
56
|
+
end
|
57
|
+
|
58
|
+
def country_code
|
59
|
+
"NL"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
data/lib/geocoder/version.rb
CHANGED
data/lib/maxmind_database.rb
CHANGED
@@ -6,9 +6,9 @@ module Geocoder
|
|
6
6
|
extend self
|
7
7
|
|
8
8
|
def download(package, dir = "tmp")
|
9
|
-
filepath = File.expand_path(File.join(dir,
|
9
|
+
filepath = File.expand_path(File.join(dir, "#{archive_edition(package)}.zip"))
|
10
10
|
open(filepath, 'wb') do |file|
|
11
|
-
uri = URI.parse(
|
11
|
+
uri = URI.parse(base_url(package))
|
12
12
|
Net::HTTP.start(uri.host, uri.port) do |http|
|
13
13
|
http.request_get(uri.path) do |resp|
|
14
14
|
# TODO: show progress
|
@@ -35,6 +35,14 @@ module Geocoder
|
|
35
35
|
p[s..-1]
|
36
36
|
end
|
37
37
|
|
38
|
+
def archive_edition(package)
|
39
|
+
{
|
40
|
+
geolite_country_csv: "GeoLite2-Country-CSV",
|
41
|
+
geolite_city_csv: "GeoLite2-City-CSV",
|
42
|
+
geolite_asn_csv: "GeoLite2-ASN-CSV"
|
43
|
+
}[package]
|
44
|
+
end
|
45
|
+
|
38
46
|
private # -------------------------------------------------------------
|
39
47
|
|
40
48
|
def table_columns(table_name)
|
@@ -94,16 +102,8 @@ module Geocoder
|
|
94
102
|
base_url + archive_url_path(package)
|
95
103
|
end
|
96
104
|
|
97
|
-
def
|
98
|
-
{
|
99
|
-
geolite_country_csv: "GeoLite2-Country-CSV.zip",
|
100
|
-
geolite_city_csv: "GeoLite2-City-CSV.zip",
|
101
|
-
geolite_asn_csv: "GeoLite2-ASN-CSV.zip"
|
102
|
-
}[package]
|
103
|
-
end
|
104
|
-
|
105
|
-
def base_url
|
106
|
-
"http://geolite.maxmind.com/download/geoip/database/"
|
105
|
+
def base_url(edition)
|
106
|
+
"https://download.maxmind.com/app/geoip_download?edition_id=#{edition}&license_key=#{ENV['LICENSE_KEY']}&suffix=zip"
|
107
107
|
end
|
108
108
|
end
|
109
109
|
end
|
data/lib/tasks/maxmind.rake
CHANGED
@@ -54,7 +54,7 @@ module MaxmindTask
|
|
54
54
|
end
|
55
55
|
require 'fileutils'
|
56
56
|
p = "geolite_#{package}_csv".intern
|
57
|
-
archive_filename = Geocoder::MaxmindDatabase.
|
57
|
+
archive_filename = "#{Geocoder::MaxmindDatabase.archive_edition(p)}.zip"
|
58
58
|
Zip::File.open(File.join(options[:dir], archive_filename)).each do |entry|
|
59
59
|
filepath = File.join(options[:dir], entry.name)
|
60
60
|
if File.exist? filepath
|
metadata
CHANGED
@@ -1,15 +1,43 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: geocoder
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.8.
|
4
|
+
version: 1.8.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alex Reisner
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
12
|
-
dependencies:
|
11
|
+
date: 2024-05-02 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: base64
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.1.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.1.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: csv
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 3.0.0
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 3.0.0
|
13
41
|
description: Object geocoding (by street or IP address), reverse geocoding (coordinates
|
14
42
|
to street address), distance queries for ActiveRecord and Mongoid, result caching,
|
15
43
|
and more. Designed for Rails but works with Sinatra and other Rack frameworks too.
|
@@ -60,7 +88,6 @@ files:
|
|
60
88
|
- lib/geocoder/lookups/base.rb
|
61
89
|
- lib/geocoder/lookups/bing.rb
|
62
90
|
- lib/geocoder/lookups/db_ip_com.rb
|
63
|
-
- lib/geocoder/lookups/dstk.rb
|
64
91
|
- lib/geocoder/lookups/esri.rb
|
65
92
|
- lib/geocoder/lookups/freegeoip.rb
|
66
93
|
- lib/geocoder/lookups/geoapify.rb
|
@@ -74,6 +101,8 @@ files:
|
|
74
101
|
- lib/geocoder/lookups/google_premier.rb
|
75
102
|
- lib/geocoder/lookups/here.rb
|
76
103
|
- lib/geocoder/lookups/ip2location.rb
|
104
|
+
- lib/geocoder/lookups/ip2location_io.rb
|
105
|
+
- lib/geocoder/lookups/ip2location_lite.rb
|
77
106
|
- lib/geocoder/lookups/ipapi_com.rb
|
78
107
|
- lib/geocoder/lookups/ipbase.rb
|
79
108
|
- lib/geocoder/lookups/ipdata_co.rb
|
@@ -94,6 +123,8 @@ files:
|
|
94
123
|
- lib/geocoder/lookups/nominatim.rb
|
95
124
|
- lib/geocoder/lookups/opencagedata.rb
|
96
125
|
- lib/geocoder/lookups/osmnames.rb
|
126
|
+
- lib/geocoder/lookups/pc_miler.rb
|
127
|
+
- lib/geocoder/lookups/pdok_nl.rb
|
97
128
|
- lib/geocoder/lookups/pelias.rb
|
98
129
|
- lib/geocoder/lookups/photon.rb
|
99
130
|
- lib/geocoder/lookups/pickpoint.rb
|
@@ -124,7 +155,6 @@ files:
|
|
124
155
|
- lib/geocoder/results/base.rb
|
125
156
|
- lib/geocoder/results/bing.rb
|
126
157
|
- lib/geocoder/results/db_ip_com.rb
|
127
|
-
- lib/geocoder/results/dstk.rb
|
128
158
|
- lib/geocoder/results/esri.rb
|
129
159
|
- lib/geocoder/results/freegeoip.rb
|
130
160
|
- lib/geocoder/results/geoapify.rb
|
@@ -138,6 +168,8 @@ files:
|
|
138
168
|
- lib/geocoder/results/google_premier.rb
|
139
169
|
- lib/geocoder/results/here.rb
|
140
170
|
- lib/geocoder/results/ip2location.rb
|
171
|
+
- lib/geocoder/results/ip2location_io.rb
|
172
|
+
- lib/geocoder/results/ip2location_lite.rb
|
141
173
|
- lib/geocoder/results/ipapi_com.rb
|
142
174
|
- lib/geocoder/results/ipbase.rb
|
143
175
|
- lib/geocoder/results/ipdata_co.rb
|
@@ -158,6 +190,8 @@ files:
|
|
158
190
|
- lib/geocoder/results/nominatim.rb
|
159
191
|
- lib/geocoder/results/opencagedata.rb
|
160
192
|
- lib/geocoder/results/osmnames.rb
|
193
|
+
- lib/geocoder/results/pc_miler.rb
|
194
|
+
- lib/geocoder/results/pdok_nl.rb
|
161
195
|
- lib/geocoder/results/pelias.rb
|
162
196
|
- lib/geocoder/results/photon.rb
|
163
197
|
- lib/geocoder/results/pickpoint.rb
|
@@ -188,7 +222,7 @@ licenses:
|
|
188
222
|
metadata:
|
189
223
|
source_code_uri: https://github.com/alexreisner/geocoder
|
190
224
|
changelog_uri: https://github.com/alexreisner/geocoder/blob/master/CHANGELOG.md
|
191
|
-
post_install_message:
|
225
|
+
post_install_message:
|
192
226
|
rdoc_options: []
|
193
227
|
require_paths:
|
194
228
|
- lib
|
@@ -203,8 +237,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
203
237
|
- !ruby/object:Gem::Version
|
204
238
|
version: '0'
|
205
239
|
requirements: []
|
206
|
-
rubygems_version: 3.
|
207
|
-
signing_key:
|
240
|
+
rubygems_version: 3.3.26
|
241
|
+
signing_key:
|
208
242
|
specification_version: 4
|
209
243
|
summary: Complete geocoding solution for Ruby.
|
210
244
|
test_files: []
|
@@ -1,22 +0,0 @@
|
|
1
|
-
# More information about the Data Science Toolkit can be found at:
|
2
|
-
# http://www.datasciencetoolkit.org/. The provided APIs mimic the
|
3
|
-
# Google geocoding api.
|
4
|
-
|
5
|
-
require 'geocoder/lookups/google'
|
6
|
-
require 'geocoder/results/dstk'
|
7
|
-
|
8
|
-
module Geocoder::Lookup
|
9
|
-
class Dstk < Google
|
10
|
-
|
11
|
-
def name
|
12
|
-
"Data Science Toolkit"
|
13
|
-
end
|
14
|
-
|
15
|
-
private # ----------------------------------------------------------------
|
16
|
-
|
17
|
-
def base_query_url(query)
|
18
|
-
host = configuration[:host] || "www.datasciencetoolkit.org"
|
19
|
-
"#{protocol}://#{host}/maps/api/geocode/json?"
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|