really-broken-geocoder 1.5.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 +7 -0
- data/CHANGELOG.md +557 -0
- data/LICENSE +20 -0
- data/README.md +3 -0
- data/bin/geocode +5 -0
- data/examples/autoexpire_cache_dalli.rb +62 -0
- data/examples/autoexpire_cache_redis.rb +28 -0
- data/examples/cache_bypass.rb +48 -0
- data/examples/reverse_geocode_job.rb +40 -0
- data/lib/generators/geocoder/config/config_generator.rb +14 -0
- data/lib/generators/geocoder/config/templates/initializer.rb +22 -0
- data/lib/generators/geocoder/maxmind/geolite_city_generator.rb +30 -0
- data/lib/generators/geocoder/maxmind/geolite_country_generator.rb +30 -0
- data/lib/generators/geocoder/maxmind/templates/migration/geolite_city.rb +30 -0
- data/lib/generators/geocoder/maxmind/templates/migration/geolite_country.rb +17 -0
- data/lib/generators/geocoder/migration_version.rb +15 -0
- data/lib/geocoder.rb +48 -0
- data/lib/geocoder/cache.rb +94 -0
- data/lib/geocoder/calculations.rb +420 -0
- data/lib/geocoder/cli.rb +121 -0
- data/lib/geocoder/configuration.rb +137 -0
- data/lib/geocoder/configuration_hash.rb +11 -0
- data/lib/geocoder/esri_token.rb +38 -0
- data/lib/geocoder/exceptions.rb +40 -0
- data/lib/geocoder/ip_address.rb +26 -0
- data/lib/geocoder/kernel_logger.rb +25 -0
- data/lib/geocoder/logger.rb +47 -0
- data/lib/geocoder/lookup.rb +118 -0
- data/lib/geocoder/lookups/amap.rb +63 -0
- data/lib/geocoder/lookups/baidu.rb +63 -0
- data/lib/geocoder/lookups/baidu_ip.rb +30 -0
- data/lib/geocoder/lookups/ban_data_gouv_fr.rb +130 -0
- data/lib/geocoder/lookups/base.rb +348 -0
- data/lib/geocoder/lookups/bing.rb +82 -0
- data/lib/geocoder/lookups/db_ip_com.rb +52 -0
- data/lib/geocoder/lookups/dstk.rb +22 -0
- data/lib/geocoder/lookups/esri.rb +95 -0
- data/lib/geocoder/lookups/freegeoip.rb +60 -0
- data/lib/geocoder/lookups/geocoder_ca.rb +53 -0
- data/lib/geocoder/lookups/geocoder_us.rb +51 -0
- data/lib/geocoder/lookups/geocodio.rb +42 -0
- data/lib/geocoder/lookups/geoip2.rb +45 -0
- data/lib/geocoder/lookups/geoportail_lu.rb +65 -0
- data/lib/geocoder/lookups/google.rb +95 -0
- data/lib/geocoder/lookups/google_places_details.rb +50 -0
- data/lib/geocoder/lookups/google_places_search.rb +33 -0
- data/lib/geocoder/lookups/google_premier.rb +57 -0
- data/lib/geocoder/lookups/here.rb +77 -0
- data/lib/geocoder/lookups/ip2location.rb +75 -0
- data/lib/geocoder/lookups/ipapi_com.rb +82 -0
- data/lib/geocoder/lookups/ipdata_co.rb +62 -0
- data/lib/geocoder/lookups/ipinfo_io.rb +44 -0
- data/lib/geocoder/lookups/ipstack.rb +63 -0
- data/lib/geocoder/lookups/latlon.rb +59 -0
- data/lib/geocoder/lookups/location_iq.rb +50 -0
- data/lib/geocoder/lookups/mapbox.rb +59 -0
- data/lib/geocoder/lookups/mapquest.rb +58 -0
- data/lib/geocoder/lookups/maxmind.rb +90 -0
- data/lib/geocoder/lookups/maxmind_geoip2.rb +70 -0
- data/lib/geocoder/lookups/maxmind_local.rb +65 -0
- data/lib/geocoder/lookups/nominatim.rb +64 -0
- data/lib/geocoder/lookups/opencagedata.rb +65 -0
- data/lib/geocoder/lookups/pelias.rb +63 -0
- data/lib/geocoder/lookups/pickpoint.rb +41 -0
- data/lib/geocoder/lookups/pointpin.rb +69 -0
- data/lib/geocoder/lookups/postcode_anywhere_uk.rb +50 -0
- data/lib/geocoder/lookups/postcodes_io.rb +31 -0
- data/lib/geocoder/lookups/smarty_streets.rb +63 -0
- data/lib/geocoder/lookups/telize.rb +75 -0
- data/lib/geocoder/lookups/tencent.rb +59 -0
- data/lib/geocoder/lookups/test.rb +44 -0
- data/lib/geocoder/lookups/yandex.rb +62 -0
- data/lib/geocoder/models/active_record.rb +51 -0
- data/lib/geocoder/models/base.rb +39 -0
- data/lib/geocoder/models/mongo_base.rb +62 -0
- data/lib/geocoder/models/mongo_mapper.rb +26 -0
- data/lib/geocoder/models/mongoid.rb +32 -0
- data/lib/geocoder/query.rb +125 -0
- data/lib/geocoder/railtie.rb +26 -0
- data/lib/geocoder/request.rb +114 -0
- data/lib/geocoder/results/amap.rb +87 -0
- data/lib/geocoder/results/baidu.rb +79 -0
- data/lib/geocoder/results/baidu_ip.rb +62 -0
- data/lib/geocoder/results/ban_data_gouv_fr.rb +257 -0
- data/lib/geocoder/results/base.rb +79 -0
- data/lib/geocoder/results/bing.rb +52 -0
- data/lib/geocoder/results/db_ip_com.rb +58 -0
- data/lib/geocoder/results/dstk.rb +6 -0
- data/lib/geocoder/results/esri.rb +75 -0
- data/lib/geocoder/results/freegeoip.rb +40 -0
- data/lib/geocoder/results/geocoder_ca.rb +60 -0
- data/lib/geocoder/results/geocoder_us.rb +39 -0
- data/lib/geocoder/results/geocodio.rb +78 -0
- data/lib/geocoder/results/geoip2.rb +76 -0
- data/lib/geocoder/results/geoportail_lu.rb +71 -0
- data/lib/geocoder/results/google.rb +150 -0
- data/lib/geocoder/results/google_places_details.rb +39 -0
- data/lib/geocoder/results/google_places_search.rb +52 -0
- data/lib/geocoder/results/google_premier.rb +6 -0
- data/lib/geocoder/results/here.rb +79 -0
- data/lib/geocoder/results/ip2location.rb +22 -0
- data/lib/geocoder/results/ipapi_com.rb +45 -0
- data/lib/geocoder/results/ipdata_co.rb +40 -0
- data/lib/geocoder/results/ipinfo_io.rb +48 -0
- data/lib/geocoder/results/ipstack.rb +60 -0
- data/lib/geocoder/results/latlon.rb +71 -0
- data/lib/geocoder/results/location_iq.rb +6 -0
- data/lib/geocoder/results/mapbox.rb +57 -0
- data/lib/geocoder/results/mapquest.rb +48 -0
- data/lib/geocoder/results/maxmind.rb +130 -0
- data/lib/geocoder/results/maxmind_geoip2.rb +9 -0
- data/lib/geocoder/results/maxmind_local.rb +44 -0
- data/lib/geocoder/results/nominatim.rb +109 -0
- data/lib/geocoder/results/opencagedata.rb +100 -0
- data/lib/geocoder/results/pelias.rb +58 -0
- data/lib/geocoder/results/pickpoint.rb +6 -0
- data/lib/geocoder/results/pointpin.rb +40 -0
- data/lib/geocoder/results/postcode_anywhere_uk.rb +42 -0
- data/lib/geocoder/results/postcodes_io.rb +40 -0
- data/lib/geocoder/results/smarty_streets.rb +142 -0
- data/lib/geocoder/results/telize.rb +40 -0
- data/lib/geocoder/results/tencent.rb +72 -0
- data/lib/geocoder/results/test.rb +33 -0
- data/lib/geocoder/results/yandex.rb +134 -0
- data/lib/geocoder/sql.rb +110 -0
- data/lib/geocoder/stores/active_record.rb +328 -0
- data/lib/geocoder/stores/base.rb +115 -0
- data/lib/geocoder/stores/mongo_base.rb +58 -0
- data/lib/geocoder/stores/mongo_mapper.rb +13 -0
- data/lib/geocoder/stores/mongoid.rb +13 -0
- data/lib/geocoder/version.rb +3 -0
- data/lib/hash_recursive_merge.rb +74 -0
- data/lib/maxmind_database.rb +109 -0
- data/lib/tasks/geocoder.rake +54 -0
- data/lib/tasks/maxmind.rake +73 -0
- metadata +186 -0
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'geocoder/lookups/base'
|
2
|
+
require "geocoder/results/bing"
|
3
|
+
|
4
|
+
module Geocoder::Lookup
|
5
|
+
class Bing < Base
|
6
|
+
|
7
|
+
def name
|
8
|
+
"Bing"
|
9
|
+
end
|
10
|
+
|
11
|
+
def map_link_url(coordinates)
|
12
|
+
"http://www.bing.com/maps/default.aspx?cp=#{coordinates.join('~')}"
|
13
|
+
end
|
14
|
+
|
15
|
+
def required_api_key_parts
|
16
|
+
["key"]
|
17
|
+
end
|
18
|
+
|
19
|
+
private # ---------------------------------------------------------------
|
20
|
+
|
21
|
+
def base_query_url(query)
|
22
|
+
text = CGI.escape(query.sanitized_text.strip)
|
23
|
+
url = "#{protocol}://dev.virtualearth.net/REST/v1/Locations/"
|
24
|
+
if query.reverse_geocode?
|
25
|
+
url + "#{text}?"
|
26
|
+
else
|
27
|
+
if r = query.options[:region]
|
28
|
+
url << "#{r}/"
|
29
|
+
end
|
30
|
+
# use the more forgiving 'unstructured' query format to allow special
|
31
|
+
# chars, newlines, brackets, typos.
|
32
|
+
url + "?q=#{text}&"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def results(query)
|
37
|
+
return [] unless doc = fetch_data(query)
|
38
|
+
|
39
|
+
if doc['statusCode'] == 200
|
40
|
+
return doc['resourceSets'].first['estimatedTotal'] > 0 ? doc['resourceSets'].first['resources'] : []
|
41
|
+
elsif doc['statusCode'] == 401 and doc["authenticationResultCode"] == "InvalidCredentials"
|
42
|
+
raise_error(Geocoder::InvalidApiKey) || Geocoder.log(:warn, "Invalid Bing API key.")
|
43
|
+
elsif doc['statusCode'] == 403
|
44
|
+
raise_error(Geocoder::RequestDenied) || Geocoder.log(:warn, "Bing Geocoding API error: Forbidden Request")
|
45
|
+
elsif [500, 503].include?(doc['statusCode'])
|
46
|
+
raise_error(Geocoder::ServiceUnavailable) ||
|
47
|
+
Geocoder.log(:warn, "Bing Geocoding API error: Service Unavailable")
|
48
|
+
else
|
49
|
+
Geocoder.log(:warn, "Bing Geocoding API error: #{doc['statusCode']} (#{doc['statusDescription']}).")
|
50
|
+
end
|
51
|
+
return []
|
52
|
+
end
|
53
|
+
|
54
|
+
def query_url_params(query)
|
55
|
+
{
|
56
|
+
key: configuration.api_key,
|
57
|
+
language: (query.language || configuration.language)
|
58
|
+
}.merge(super)
|
59
|
+
end
|
60
|
+
|
61
|
+
def check_response_for_errors!(response)
|
62
|
+
super
|
63
|
+
if server_overloaded?(response)
|
64
|
+
raise_error(Geocoder::ServiceUnavailable) ||
|
65
|
+
Geocoder.log(:warn, "Bing Geocoding API error: Service Unavailable")
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def valid_response?(response)
|
70
|
+
super(response) and not server_overloaded?(response)
|
71
|
+
end
|
72
|
+
|
73
|
+
def server_overloaded?(response)
|
74
|
+
# Occasionally, the servers processing service requests can be overloaded,
|
75
|
+
# and you may receive some responses that contain no results for queries that
|
76
|
+
# you would normally receive a result. To identify this situation,
|
77
|
+
# check the HTTP headers of the response. If the HTTP header X-MS-BM-WS-INFO is set to 1,
|
78
|
+
# it is best to wait a few seconds and try again.
|
79
|
+
response['x-ms-bm-ws-info'].to_i == 1
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'geocoder/lookups/base'
|
2
|
+
require 'geocoder/results/db_ip_com'
|
3
|
+
|
4
|
+
module Geocoder::Lookup
|
5
|
+
class DbIpCom < Base
|
6
|
+
|
7
|
+
def name
|
8
|
+
'DB-IP.com'
|
9
|
+
end
|
10
|
+
|
11
|
+
def supported_protocols
|
12
|
+
[:https, :http]
|
13
|
+
end
|
14
|
+
|
15
|
+
def required_api_key_parts
|
16
|
+
['api_key']
|
17
|
+
end
|
18
|
+
|
19
|
+
private # ----------------------------------------------------------------
|
20
|
+
|
21
|
+
def base_query_url(query)
|
22
|
+
"#{protocol}://api.db-ip.com/v2/#{configuration.api_key}/#{query.sanitized_text}?"
|
23
|
+
end
|
24
|
+
|
25
|
+
##
|
26
|
+
# Same as query_url but without the api key.
|
27
|
+
#
|
28
|
+
def cache_key(query)
|
29
|
+
"#{protocol}://api.db-ip.com/v2/#{query.sanitized_text}?" + hash_to_query(cache_key_params(query))
|
30
|
+
end
|
31
|
+
|
32
|
+
def results(query)
|
33
|
+
return [] unless (doc = fetch_data(query))
|
34
|
+
|
35
|
+
case doc['error']
|
36
|
+
when 'maximum number of queries per day exceeded'
|
37
|
+
raise_error Geocoder::OverQueryLimitError ||
|
38
|
+
Geocoder.log(:warn, 'DB-API query limit exceeded.')
|
39
|
+
|
40
|
+
when 'invalid API key'
|
41
|
+
raise_error Geocoder::InvalidApiKey ||
|
42
|
+
Geocoder.log(:warn, 'Invalid DB-IP API key.')
|
43
|
+
when nil
|
44
|
+
[doc]
|
45
|
+
|
46
|
+
else
|
47
|
+
raise_error Geocoder::Error ||
|
48
|
+
Geocoder.log(:warn, "Request failed: #{doc['error']}")
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,22 @@
|
|
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
|
@@ -0,0 +1,95 @@
|
|
1
|
+
require 'geocoder/lookups/base'
|
2
|
+
require "geocoder/results/esri"
|
3
|
+
require 'geocoder/esri_token'
|
4
|
+
|
5
|
+
module Geocoder::Lookup
|
6
|
+
class Esri < Base
|
7
|
+
|
8
|
+
def name
|
9
|
+
"Esri"
|
10
|
+
end
|
11
|
+
|
12
|
+
private # ---------------------------------------------------------------
|
13
|
+
|
14
|
+
def base_query_url(query)
|
15
|
+
action = query.reverse_geocode? ? "reverseGeocode" : "find"
|
16
|
+
"#{protocol}://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer/#{action}?"
|
17
|
+
end
|
18
|
+
|
19
|
+
def results(query)
|
20
|
+
return [] unless doc = fetch_data(query)
|
21
|
+
|
22
|
+
if (!query.reverse_geocode?)
|
23
|
+
return [] if !doc['locations'] || doc['locations'].empty?
|
24
|
+
end
|
25
|
+
|
26
|
+
if (doc['error'].nil?)
|
27
|
+
return [ doc ]
|
28
|
+
else
|
29
|
+
return []
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def query_url_params(query)
|
34
|
+
params = {
|
35
|
+
:f => "pjson",
|
36
|
+
:outFields => "*"
|
37
|
+
}
|
38
|
+
if query.reverse_geocode?
|
39
|
+
params[:location] = query.coordinates.reverse.join(',')
|
40
|
+
else
|
41
|
+
params[:text] = query.sanitized_text
|
42
|
+
end
|
43
|
+
|
44
|
+
params[:token] = token(query)
|
45
|
+
|
46
|
+
if for_storage_value = for_storage(query)
|
47
|
+
params[:forStorage] = for_storage_value
|
48
|
+
end
|
49
|
+
params[:sourceCountry] = configuration[:source_country] if configuration[:source_country]
|
50
|
+
params.merge(super)
|
51
|
+
end
|
52
|
+
|
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?
|
73
|
+
end
|
74
|
+
|
75
|
+
def valid_token_configured?(token_instance)
|
76
|
+
!token_instance.nil? && token_instance.active?
|
77
|
+
end
|
78
|
+
|
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
|
89
|
+
end
|
90
|
+
|
91
|
+
def create_token
|
92
|
+
Geocoder::EsriToken.generate_token(*configuration.api_key)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'geocoder/lookups/base'
|
2
|
+
require 'geocoder/results/freegeoip'
|
3
|
+
|
4
|
+
module Geocoder::Lookup
|
5
|
+
class Freegeoip < Base
|
6
|
+
|
7
|
+
def name
|
8
|
+
"FreeGeoIP"
|
9
|
+
end
|
10
|
+
|
11
|
+
def supported_protocols
|
12
|
+
if configuration[:host]
|
13
|
+
[:http, :https]
|
14
|
+
else
|
15
|
+
# use https for default host
|
16
|
+
[:https]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def query_url(query)
|
21
|
+
"#{protocol}://#{host}/json/#{query.sanitized_text}"
|
22
|
+
end
|
23
|
+
|
24
|
+
private # ---------------------------------------------------------------
|
25
|
+
|
26
|
+
def cache_key(query)
|
27
|
+
query_url(query)
|
28
|
+
end
|
29
|
+
|
30
|
+
def parse_raw_data(raw_data)
|
31
|
+
raw_data.match(/^<html><title>404/) ? nil : super(raw_data)
|
32
|
+
end
|
33
|
+
|
34
|
+
def results(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
|
+
# note: Freegeoip.net returns plain text "Not Found" on bad request
|
38
|
+
(doc = fetch_data(query)) ? [doc] : []
|
39
|
+
end
|
40
|
+
|
41
|
+
def reserved_result(ip)
|
42
|
+
{
|
43
|
+
"ip" => ip,
|
44
|
+
"city" => "",
|
45
|
+
"region_code" => "",
|
46
|
+
"region_name" => "",
|
47
|
+
"metrocode" => "",
|
48
|
+
"zipcode" => "",
|
49
|
+
"latitude" => "0",
|
50
|
+
"longitude" => "0",
|
51
|
+
"country_name" => "Reserved",
|
52
|
+
"country_code" => "RD"
|
53
|
+
}
|
54
|
+
end
|
55
|
+
|
56
|
+
def host
|
57
|
+
configuration[:host] || "freegeoip.net"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'geocoder/lookups/base'
|
2
|
+
require "geocoder/results/geocoder_ca"
|
3
|
+
|
4
|
+
module Geocoder::Lookup
|
5
|
+
class GeocoderCa < Base
|
6
|
+
|
7
|
+
def name
|
8
|
+
"Geocoder.ca"
|
9
|
+
end
|
10
|
+
|
11
|
+
private # ---------------------------------------------------------------
|
12
|
+
|
13
|
+
def base_query_url(query)
|
14
|
+
"#{protocol}://geocoder.ca/?"
|
15
|
+
end
|
16
|
+
|
17
|
+
def results(query)
|
18
|
+
return [] unless doc = fetch_data(query)
|
19
|
+
if doc['error'].nil?
|
20
|
+
return [doc]
|
21
|
+
elsif doc['error']['code'] == "005"
|
22
|
+
# "Postal Code is not in the proper Format" => no results, just shut up
|
23
|
+
else
|
24
|
+
Geocoder.log(:warn, "Geocoder.ca service error: #{doc['error']['code']} (#{doc['error']['description']}).")
|
25
|
+
end
|
26
|
+
return []
|
27
|
+
end
|
28
|
+
|
29
|
+
def query_url_params(query)
|
30
|
+
params = {
|
31
|
+
:geoit => "xml",
|
32
|
+
:jsonp => 1,
|
33
|
+
:callback => "test",
|
34
|
+
:auth => configuration.api_key
|
35
|
+
}.merge(super)
|
36
|
+
if query.reverse_geocode?
|
37
|
+
lat,lon = query.coordinates
|
38
|
+
params[:latt] = lat
|
39
|
+
params[:longt] = lon
|
40
|
+
params[:corner] = 1
|
41
|
+
params[:reverse] = 1
|
42
|
+
else
|
43
|
+
params[:locate] = query.sanitized_text
|
44
|
+
params[:showpostal] = 1
|
45
|
+
end
|
46
|
+
params
|
47
|
+
end
|
48
|
+
|
49
|
+
def parse_raw_data(raw_data)
|
50
|
+
super raw_data[/^test\((.*)\)\;\s*$/, 1]
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'geocoder/lookups/base'
|
2
|
+
require "geocoder/results/geocoder_us"
|
3
|
+
|
4
|
+
module Geocoder::Lookup
|
5
|
+
class GeocoderUs < Base
|
6
|
+
|
7
|
+
def name
|
8
|
+
"Geocoder.us"
|
9
|
+
end
|
10
|
+
|
11
|
+
def supported_protocols
|
12
|
+
[:http]
|
13
|
+
end
|
14
|
+
|
15
|
+
private # ----------------------------------------------------------------
|
16
|
+
|
17
|
+
def base_query_url(query)
|
18
|
+
base_query_url_with_optional_key(configuration.api_key)
|
19
|
+
end
|
20
|
+
|
21
|
+
def cache_key(query)
|
22
|
+
base_query_url_with_optional_key(nil) + url_query_string(query)
|
23
|
+
end
|
24
|
+
|
25
|
+
def base_query_url_with_optional_key(key = nil)
|
26
|
+
base = "#{protocol}://"
|
27
|
+
if configuration.api_key
|
28
|
+
base << "#{configuration.api_key}@"
|
29
|
+
end
|
30
|
+
base + "geocoder.us/member/service/csv/geocode?"
|
31
|
+
end
|
32
|
+
|
33
|
+
def results(query)
|
34
|
+
return [] unless doc = fetch_data(query)
|
35
|
+
if doc[0].to_s =~ /^(\d+)\:/
|
36
|
+
return []
|
37
|
+
else
|
38
|
+
return [doc.size == 5 ? ((doc[0..1] << nil) + doc[2..4]) : doc]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def query_url_params(query)
|
43
|
+
(query.text =~ /^\d{5}(?:-\d{4})?$/ ? {:zip => query} : {:address => query.sanitized_text}).merge(super)
|
44
|
+
end
|
45
|
+
|
46
|
+
def parse_raw_data(raw_data)
|
47
|
+
raw_data.chomp.split(',')
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'geocoder/lookups/base'
|
2
|
+
require "geocoder/results/geocodio"
|
3
|
+
|
4
|
+
module Geocoder::Lookup
|
5
|
+
class Geocodio < Base
|
6
|
+
|
7
|
+
def name
|
8
|
+
"Geocodio"
|
9
|
+
end
|
10
|
+
|
11
|
+
def results(query)
|
12
|
+
return [] unless doc = fetch_data(query)
|
13
|
+
return doc["results"] if doc['error'].nil?
|
14
|
+
|
15
|
+
if doc['error'] == 'Invalid API key'
|
16
|
+
raise_error(Geocoder::InvalidApiKey) ||
|
17
|
+
Geocoder.log(:warn, "Geocodio service error: invalid API key.")
|
18
|
+
elsif doc['error'].match(/You have reached your daily maximum/)
|
19
|
+
raise_error(Geocoder::OverQueryLimitError, doc['error']) ||
|
20
|
+
Geocoder.log(:warn, "Geocodio service error: #{doc['error']}.")
|
21
|
+
else
|
22
|
+
raise_error(Geocoder::InvalidRequest, doc['error']) ||
|
23
|
+
Geocoder.log(:warn, "Geocodio service error: #{doc['error']}.")
|
24
|
+
end
|
25
|
+
[]
|
26
|
+
end
|
27
|
+
|
28
|
+
private # ---------------------------------------------------------------
|
29
|
+
|
30
|
+
def base_query_url(query)
|
31
|
+
path = query.reverse_geocode? ? "reverse" : "geocode"
|
32
|
+
"#{protocol}://api.geocod.io/v1.3/#{path}?"
|
33
|
+
end
|
34
|
+
|
35
|
+
def query_url_params(query)
|
36
|
+
{
|
37
|
+
:api_key => configuration.api_key,
|
38
|
+
:q => query.sanitized_text
|
39
|
+
}.merge(super)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|