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,69 @@
|
|
1
|
+
require 'geocoder/lookups/base'
|
2
|
+
require 'geocoder/results/pointpin'
|
3
|
+
|
4
|
+
module Geocoder::Lookup
|
5
|
+
class Pointpin < Base
|
6
|
+
|
7
|
+
def name
|
8
|
+
"Pointpin"
|
9
|
+
end
|
10
|
+
|
11
|
+
def required_api_key_parts
|
12
|
+
["key"]
|
13
|
+
end
|
14
|
+
|
15
|
+
def query_url(query)
|
16
|
+
"#{protocol}://geo.pointp.in/#{configuration.api_key}/json/#{query.sanitized_text}"
|
17
|
+
end
|
18
|
+
|
19
|
+
private # ----------------------------------------------------------------
|
20
|
+
|
21
|
+
def cache_key(query)
|
22
|
+
"#{protocol}://geo.pointp.in/json/#{query.sanitized_text}"
|
23
|
+
end
|
24
|
+
|
25
|
+
def results(query)
|
26
|
+
# don't look up a loopback or private address, just return the stored result
|
27
|
+
return [] if query.internal_ip_address?
|
28
|
+
doc = fetch_data(query)
|
29
|
+
if doc and doc.is_a?(Hash)
|
30
|
+
if !data_contains_error?(doc)
|
31
|
+
return [doc]
|
32
|
+
elsif doc['error']
|
33
|
+
case doc['error']
|
34
|
+
when "Invalid IP address"
|
35
|
+
raise_error(Geocoder::InvalidRequest) || Geocoder.log(:warn, "Invalid Pointpin request.")
|
36
|
+
when "Invalid API key"
|
37
|
+
raise_error(Geocoder::InvalidApiKey) || Geocoder.log(:warn, "Invalid Pointpin API key.")
|
38
|
+
when "Address not found"
|
39
|
+
Geocoder.log(:warn, "Address not found.")
|
40
|
+
end
|
41
|
+
else
|
42
|
+
raise_error(Geocoder::Error) || Geocoder.log(:warn, "Pointpin server error")
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
return []
|
47
|
+
end
|
48
|
+
|
49
|
+
def data_contains_error?(parsed_data)
|
50
|
+
parsed_data.keys.include?('error')
|
51
|
+
end
|
52
|
+
|
53
|
+
# TODO: replace this hash with what's actually returned by Pointpin
|
54
|
+
def reserved_result(ip)
|
55
|
+
{
|
56
|
+
"ip" => ip,
|
57
|
+
"city" => "",
|
58
|
+
"region_code" => "",
|
59
|
+
"region_name" => "",
|
60
|
+
"metrocode" => "",
|
61
|
+
"zipcode" => "",
|
62
|
+
"latitude" => "0",
|
63
|
+
"longitude" => "0",
|
64
|
+
"country_name" => "Reserved",
|
65
|
+
"country_code" => "RD"
|
66
|
+
}
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'geocoder/lookups/base'
|
2
|
+
require 'geocoder/results/postcode_anywhere_uk'
|
3
|
+
|
4
|
+
module Geocoder::Lookup
|
5
|
+
class PostcodeAnywhereUk < Base
|
6
|
+
# API documentation: http://www.postcodeanywhere.co.uk/Support/WebService/Geocoding/UK/Geocode/2/
|
7
|
+
DAILY_LIMIT_EXEEDED_ERROR_CODES = ['8', '17'] # api docs say these two codes are the same error
|
8
|
+
INVALID_API_KEY_ERROR_CODE = '2'
|
9
|
+
|
10
|
+
def name
|
11
|
+
'PostcodeAnywhereUk'
|
12
|
+
end
|
13
|
+
|
14
|
+
def required_api_key_parts
|
15
|
+
%w(key)
|
16
|
+
end
|
17
|
+
|
18
|
+
private # ----------------------------------------------------------------
|
19
|
+
|
20
|
+
def base_query_url(query)
|
21
|
+
"#{protocol}://services.postcodeanywhere.co.uk/Geocoding/UK/Geocode/v2.00/json.ws?"
|
22
|
+
end
|
23
|
+
|
24
|
+
def results(query)
|
25
|
+
response = fetch_data(query)
|
26
|
+
return [] if response.nil? || !response.is_a?(Array) || response.empty?
|
27
|
+
|
28
|
+
raise_exception_for_response(response[0]) if response[0]['Error']
|
29
|
+
response
|
30
|
+
end
|
31
|
+
|
32
|
+
def raise_exception_for_response(response)
|
33
|
+
case response['Error']
|
34
|
+
when *DAILY_LIMIT_EXEEDED_ERROR_CODES
|
35
|
+
raise_error(Geocoder::OverQueryLimitError, response['Cause']) || Geocoder.log(:warn, response['Cause'])
|
36
|
+
when INVALID_API_KEY_ERROR_CODE
|
37
|
+
raise_error(Geocoder::InvalidApiKey, response['Cause']) || Geocoder.log(:warn, response['Cause'])
|
38
|
+
else # anything else just raise general error with the api cause
|
39
|
+
raise_error(Geocoder::Error, response['Cause']) || Geocoder.log(:warn, response['Cause'])
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def query_url_params(query)
|
44
|
+
{
|
45
|
+
:location => query.sanitized_text,
|
46
|
+
:key => configuration.api_key
|
47
|
+
}.merge(super)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'geocoder/lookups/base'
|
2
|
+
require 'geocoder/results/postcodes_io'
|
3
|
+
|
4
|
+
module Geocoder::Lookup
|
5
|
+
class PostcodesIo < Base
|
6
|
+
def name
|
7
|
+
'Postcodes.io'
|
8
|
+
end
|
9
|
+
|
10
|
+
def query_url(query)
|
11
|
+
"#{protocol}://api.postcodes.io/postcodes/#{query.sanitized_text.gsub(/\s/, '')}"
|
12
|
+
end
|
13
|
+
|
14
|
+
def supported_protocols
|
15
|
+
[:https]
|
16
|
+
end
|
17
|
+
|
18
|
+
private # ----------------------------------------------------------------
|
19
|
+
|
20
|
+
def cache_key(query)
|
21
|
+
query_url(query)
|
22
|
+
end
|
23
|
+
|
24
|
+
def results(query)
|
25
|
+
response = fetch_data(query)
|
26
|
+
return [] if response.nil? || response['status'] != 200 || response.empty?
|
27
|
+
|
28
|
+
[response['result']]
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'geocoder/lookups/base'
|
2
|
+
require 'geocoder/results/smarty_streets'
|
3
|
+
|
4
|
+
module Geocoder::Lookup
|
5
|
+
class SmartyStreets < Base
|
6
|
+
def name
|
7
|
+
"SmartyStreets"
|
8
|
+
end
|
9
|
+
|
10
|
+
def required_api_key_parts
|
11
|
+
%w(auth-id auth-token)
|
12
|
+
end
|
13
|
+
|
14
|
+
# required by API as of 26 March 2015
|
15
|
+
def supported_protocols
|
16
|
+
[:https]
|
17
|
+
end
|
18
|
+
|
19
|
+
private # ---------------------------------------------------------------
|
20
|
+
|
21
|
+
def base_query_url(query)
|
22
|
+
if international?(query)
|
23
|
+
"#{protocol}://international-street.api.smartystreets.com/verify?"
|
24
|
+
elsif zipcode_only?(query)
|
25
|
+
"#{protocol}://us-zipcode.api.smartystreets.com/lookup?"
|
26
|
+
else
|
27
|
+
"#{protocol}://us-street.api.smartystreets.com/street-address?"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def zipcode_only?(query)
|
32
|
+
!query.text.is_a?(Array) and query.to_s.strip =~ /\A\d{5}(-\d{4})?\Z/
|
33
|
+
end
|
34
|
+
|
35
|
+
def international?(query)
|
36
|
+
!query.options[:country].nil?
|
37
|
+
end
|
38
|
+
|
39
|
+
def query_url_params(query)
|
40
|
+
params = {}
|
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)
|
46
|
+
params[:zipcode] = query.sanitized_text
|
47
|
+
else
|
48
|
+
params[:street] = query.sanitized_text
|
49
|
+
end
|
50
|
+
if configuration.api_key.is_a?(Array)
|
51
|
+
params[:"auth-id"] = configuration.api_key[0]
|
52
|
+
params[:"auth-token"] = configuration.api_key[1]
|
53
|
+
else
|
54
|
+
params[:"auth-token"] = configuration.api_key
|
55
|
+
end
|
56
|
+
params.merge(super)
|
57
|
+
end
|
58
|
+
|
59
|
+
def results(query)
|
60
|
+
fetch_data(query) || []
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'geocoder/lookups/base'
|
2
|
+
require 'geocoder/results/telize'
|
3
|
+
|
4
|
+
module Geocoder::Lookup
|
5
|
+
class Telize < Base
|
6
|
+
|
7
|
+
def name
|
8
|
+
"Telize"
|
9
|
+
end
|
10
|
+
|
11
|
+
def required_api_key_parts
|
12
|
+
configuration[:host] ? [] : ["key"]
|
13
|
+
end
|
14
|
+
|
15
|
+
def query_url(query)
|
16
|
+
if configuration[:host]
|
17
|
+
"#{protocol}://#{configuration[:host]}/location/#{query.sanitized_text}"
|
18
|
+
else
|
19
|
+
"#{protocol}://telize-v1.p.mashape.com/location/#{query.sanitized_text}?mashape-key=#{api_key}"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def supported_protocols
|
24
|
+
[].tap do |array|
|
25
|
+
array << :https
|
26
|
+
array << :http if configuration[:host]
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
private # ---------------------------------------------------------------
|
31
|
+
|
32
|
+
def cache_key(query)
|
33
|
+
query_url(query)[/(.*)\?.*/, 1]
|
34
|
+
end
|
35
|
+
|
36
|
+
def results(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
|
+
if (doc = fetch_data(query)).nil? or doc['code'] == 401 or empty_result?(doc)
|
40
|
+
[]
|
41
|
+
else
|
42
|
+
[doc]
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def empty_result?(doc)
|
47
|
+
!doc.is_a?(Hash) or doc.keys == ["ip"]
|
48
|
+
end
|
49
|
+
|
50
|
+
def reserved_result(ip)
|
51
|
+
{
|
52
|
+
"ip" => ip,
|
53
|
+
"latitude" => 0,
|
54
|
+
"longitude" => 0,
|
55
|
+
"city" => "",
|
56
|
+
"timezone" => "",
|
57
|
+
"asn" => 0,
|
58
|
+
"region" => "",
|
59
|
+
"offset" => 0,
|
60
|
+
"organization" => "",
|
61
|
+
"country_code" => "",
|
62
|
+
"country_code3" => "",
|
63
|
+
"postal_code" => "",
|
64
|
+
"continent_code" => "",
|
65
|
+
"country" => "",
|
66
|
+
"region_code" => ""
|
67
|
+
}
|
68
|
+
end
|
69
|
+
|
70
|
+
def api_key
|
71
|
+
configuration.api_key
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
end
|
@@ -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
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'geocoder/lookups/base'
|
2
|
+
require 'geocoder/results/test'
|
3
|
+
|
4
|
+
module Geocoder
|
5
|
+
module Lookup
|
6
|
+
class Test < Base
|
7
|
+
|
8
|
+
def name
|
9
|
+
"Test"
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.add_stub(query_text, results)
|
13
|
+
stubs[query_text] = results
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.set_default_stub(results)
|
17
|
+
@default_stub = results
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.read_stub(query_text)
|
21
|
+
stubs.fetch(query_text) {
|
22
|
+
return @default_stub unless @default_stub.nil?
|
23
|
+
raise ArgumentError, "unknown stub request #{query_text}"
|
24
|
+
}
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.stubs
|
28
|
+
@stubs ||= {}
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.reset
|
32
|
+
@stubs = {}
|
33
|
+
@default_stub = nil
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def results(query)
|
39
|
+
Geocoder::Lookup::Test.read_stub(query.text)
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'geocoder/lookups/base'
|
2
|
+
require "geocoder/results/yandex"
|
3
|
+
|
4
|
+
module Geocoder::Lookup
|
5
|
+
class Yandex < Base
|
6
|
+
|
7
|
+
def name
|
8
|
+
"Yandex"
|
9
|
+
end
|
10
|
+
|
11
|
+
def map_link_url(coordinates)
|
12
|
+
"http://maps.yandex.ru/?ll=#{coordinates.reverse.join(',')}"
|
13
|
+
end
|
14
|
+
|
15
|
+
def supported_protocols
|
16
|
+
[:https]
|
17
|
+
end
|
18
|
+
|
19
|
+
private # ---------------------------------------------------------------
|
20
|
+
|
21
|
+
def base_query_url(query)
|
22
|
+
"#{protocol}://geocode-maps.yandex.ru/1.x/?"
|
23
|
+
end
|
24
|
+
|
25
|
+
def results(query)
|
26
|
+
return [] unless doc = fetch_data(query)
|
27
|
+
if err = doc['error']
|
28
|
+
if err["status"] == 401 and err["message"] == "invalid key"
|
29
|
+
raise_error(Geocoder::InvalidApiKey) || Geocoder.log(:warn, "Invalid API key.")
|
30
|
+
else
|
31
|
+
Geocoder.log(:warn, "Yandex Geocoding API error: #{err['status']} (#{err['message']}).")
|
32
|
+
end
|
33
|
+
return []
|
34
|
+
end
|
35
|
+
if doc = doc['response']['GeoObjectCollection']
|
36
|
+
meta = doc['metaDataProperty']['GeocoderResponseMetaData']
|
37
|
+
return meta['found'].to_i > 0 ? doc['featureMember'] : []
|
38
|
+
else
|
39
|
+
Geocoder.log(:warn, "Yandex Geocoding API error: unexpected response format.")
|
40
|
+
return []
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def query_url_params(query)
|
45
|
+
if query.reverse_geocode?
|
46
|
+
q = query.coordinates.reverse.join(",")
|
47
|
+
else
|
48
|
+
q = query.sanitized_text
|
49
|
+
end
|
50
|
+
params = {
|
51
|
+
:geocode => q,
|
52
|
+
:format => "json",
|
53
|
+
:plng => "#{query.language || configuration.language}", # supports ru, uk, be
|
54
|
+
:key => configuration.api_key
|
55
|
+
}
|
56
|
+
unless (bounds = query.options[:bounds]).nil?
|
57
|
+
params[:bbox] = bounds.map{ |point| "%f,%f" % point }.join('~')
|
58
|
+
end
|
59
|
+
params.merge(super)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|