graticule 0.2.2 → 0.2.3
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.
- data/CHANGELOG.txt +4 -0
- data/Manifest.txt +9 -0
- data/Rakefile +69 -0
- data/lib/graticule.rb +2 -0
- data/lib/graticule/cli.rb +6 -4
- data/lib/graticule/geocoder/base.rb +112 -0
- data/lib/graticule/geocoder/geocoder_us.rb +1 -1
- data/lib/graticule/geocoder/google.rb +5 -5
- data/lib/graticule/geocoder/host_ip.rb +9 -18
- data/lib/graticule/geocoder/local_search_maps.rb +4 -4
- data/lib/graticule/geocoder/meta_carta.rb +1 -6
- data/lib/graticule/geocoder/rest.rb +6 -98
- data/lib/graticule/geocoder/yahoo.rb +1 -13
- data/lib/graticule/version.rb +1 -1
- data/site/index.html +114 -0
- data/site/plugin.html +82 -0
- data/site/stylesheets/style.css +73 -0
- data/test/config.yml.default +36 -0
- data/test/fixtures/responses/geocoder_us/success.xml +13 -5
- data/test/fixtures/responses/geocoder_us/unknown.xml +1 -1
- data/test/fixtures/responses/google/badkey.xml +1 -10
- data/test/fixtures/responses/google/missing_address.xml +1 -10
- data/test/fixtures/responses/google/partial.xml +1 -0
- data/test/fixtures/responses/google/success.xml +1 -37
- data/test/fixtures/responses/google/unavailable.xml +1 -10
- data/test/fixtures/responses/google/unknown_address.xml +1 -10
- data/test/fixtures/responses/host_ip/private.txt +1 -1
- data/test/fixtures/responses/host_ip/success.txt +1 -1
- data/test/fixtures/responses/host_ip/unknown.txt +1 -1
- data/test/fixtures/responses/local_search_maps/empty.txt +1 -0
- data/test/fixtures/responses/local_search_maps/not_found.txt +1 -0
- data/test/fixtures/responses/local_search_maps/success.txt +1 -1
- data/test/fixtures/responses/meta_carta/bad_address.xml +15 -7
- data/test/fixtures/responses/meta_carta/success.xml +29 -21
- data/test/fixtures/responses/yahoo/success.xml +2 -2
- data/test/fixtures/responses/yahoo/unknown_address.xml +6 -6
- data/test/mocks/uri.rb +3 -2
- data/test/unit/graticule/geocoder/google_test.rb +14 -0
- data/test/unit/graticule/geocoder/host_ip_test.rb +1 -0
- data/test/unit/graticule/geocoder/meta_carta_test.rb +1 -1
- data/test/unit/graticule/location_test.rb +1 -1
- metadata +10 -3
- data/test/unit/graticule/cli_test.rb +0 -26
data/CHANGELOG.txt
CHANGED
data/Manifest.txt
CHANGED
@@ -12,6 +12,7 @@ lib/graticule/distance/haversine.rb
|
|
12
12
|
lib/graticule/distance/spherical.rb
|
13
13
|
lib/graticule/distance/vincenty.rb
|
14
14
|
lib/graticule/geocoder.rb
|
15
|
+
lib/graticule/geocoder/base.rb
|
15
16
|
lib/graticule/geocoder/bogus.rb
|
16
17
|
lib/graticule/geocoder/geocoder_ca.rb
|
17
18
|
lib/graticule/geocoder/geocoder_us.rb
|
@@ -24,11 +25,16 @@ lib/graticule/geocoder/rest.rb
|
|
24
25
|
lib/graticule/geocoder/yahoo.rb
|
25
26
|
lib/graticule/location.rb
|
26
27
|
lib/graticule/version.rb
|
28
|
+
site/index.html
|
29
|
+
site/plugin.html
|
30
|
+
site/stylesheets/style.css
|
31
|
+
test/config.yml.default
|
27
32
|
test/fixtures/responses/geocoder_us/success.xml
|
28
33
|
test/fixtures/responses/geocoder_us/unknown.xml
|
29
34
|
test/fixtures/responses/google/badkey.xml
|
30
35
|
test/fixtures/responses/google/limit.xml
|
31
36
|
test/fixtures/responses/google/missing_address.xml
|
37
|
+
test/fixtures/responses/google/partial.xml
|
32
38
|
test/fixtures/responses/google/server_error.xml
|
33
39
|
test/fixtures/responses/google/success.xml
|
34
40
|
test/fixtures/responses/google/unavailable.xml
|
@@ -36,6 +42,8 @@ test/fixtures/responses/google/unknown_address.xml
|
|
36
42
|
test/fixtures/responses/host_ip/private.txt
|
37
43
|
test/fixtures/responses/host_ip/success.txt
|
38
44
|
test/fixtures/responses/host_ip/unknown.txt
|
45
|
+
test/fixtures/responses/local_search_maps/empty.txt
|
46
|
+
test/fixtures/responses/local_search_maps/not_found.txt
|
39
47
|
test/fixtures/responses/local_search_maps/success.txt
|
40
48
|
test/fixtures/responses/meta_carta/bad_address.xml
|
41
49
|
test/fixtures/responses/meta_carta/multiple.xml
|
@@ -59,3 +67,4 @@ test/unit/graticule/geocoder/postcode_anywhere_test.rb
|
|
59
67
|
test/unit/graticule/geocoder/yahoo_test.rb
|
60
68
|
test/unit/graticule/geocoder_test.rb
|
61
69
|
test/unit/graticule/location_test.rb
|
70
|
+
|
data/Rakefile
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'rubygems'
|
2
|
+
require 'active_support'
|
2
3
|
require 'hoe'
|
3
4
|
require File.join(File.dirname(__FILE__), 'lib', 'graticule', 'version.rb')
|
4
5
|
|
@@ -15,3 +16,71 @@ Hoe.new("graticule", Graticule::Version::STRING) do |p|
|
|
15
16
|
p.changes = p.paragraphs_of('CHANGELOG.txt', 0..1).join("\n\n")
|
16
17
|
p.extra_deps << ['activesupport']
|
17
18
|
end
|
19
|
+
|
20
|
+
|
21
|
+
|
22
|
+
namespace :test do
|
23
|
+
namespace :cache do
|
24
|
+
desc 'Cache test responses from all the free geocoders'
|
25
|
+
task :free => [:google, :geocoder_us, :host_ip, :local_search_maps, :meta_carta, :yahoo]
|
26
|
+
|
27
|
+
desc 'Cache test responses from Google'
|
28
|
+
task :google do
|
29
|
+
cache_responses('google')
|
30
|
+
end
|
31
|
+
|
32
|
+
desc 'Cache test responses from Geocoder.us'
|
33
|
+
task :geocoder_us do
|
34
|
+
cache_responses('geocoder_us')
|
35
|
+
end
|
36
|
+
|
37
|
+
desc 'Cache test responses from HostIP'
|
38
|
+
task :host_ip do
|
39
|
+
cache_responses('host_ip')
|
40
|
+
end
|
41
|
+
|
42
|
+
desc 'Cache test responses from Local Search Maps'
|
43
|
+
task :local_search_maps do
|
44
|
+
cache_responses('local_search_maps')
|
45
|
+
end
|
46
|
+
|
47
|
+
desc 'Cache test responses from Meta Carta'
|
48
|
+
task :meta_carta do
|
49
|
+
cache_responses('meta_carta')
|
50
|
+
end
|
51
|
+
|
52
|
+
desc 'Cache test responses from Yahoo'
|
53
|
+
task :yahoo do
|
54
|
+
cache_responses('yahoo')
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
require 'net/http'
|
61
|
+
require 'uri'
|
62
|
+
RESPONSES_PATH = File.dirname(__FILE__) + '/test/fixtures/responses'
|
63
|
+
|
64
|
+
def cache_responses(service)
|
65
|
+
test_config[service.to_s]['responses'].each do |file,url|
|
66
|
+
File.open("#{RESPONSES_PATH}/#{service}/#{file}", 'w') do |f|
|
67
|
+
f.puts Net::HTTP.get(URI.parse(url))
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def test_config
|
73
|
+
file = File.dirname(__FILE__) + '/test/config.yml'
|
74
|
+
raise "Copy config.yml.default to config.yml and set the API keys" unless File.exists?(file)
|
75
|
+
@test_config ||= returning(YAML.load(File.read(file))) do |config|
|
76
|
+
config.each do |service,values|
|
77
|
+
values['responses'].each {|file,url| update_placeholders!(values, url) }
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def update_placeholders!(config, thing)
|
83
|
+
config.each do |option, value|
|
84
|
+
thing.gsub!(":#{option}", value) if value.is_a?(String)
|
85
|
+
end
|
86
|
+
end
|
data/lib/graticule.rb
CHANGED
@@ -2,8 +2,10 @@ $:.unshift(File.dirname(__FILE__))
|
|
2
2
|
|
3
3
|
require 'active_support'
|
4
4
|
|
5
|
+
require 'graticule/version'
|
5
6
|
require 'graticule/location'
|
6
7
|
require 'graticule/geocoder'
|
8
|
+
require 'graticule/geocoder/base'
|
7
9
|
require 'graticule/geocoder/bogus'
|
8
10
|
require 'graticule/geocoder/rest'
|
9
11
|
require 'graticule/geocoder/google'
|
data/lib/graticule/cli.rb
CHANGED
@@ -20,7 +20,7 @@ module Graticule
|
|
20
20
|
# -h, --help Help
|
21
21
|
class Cli
|
22
22
|
|
23
|
-
def self.start(args)
|
23
|
+
def self.start(args, out = STDOUT)
|
24
24
|
options = { :service => :yahoo, :api_key => 'YahooDemo' }
|
25
25
|
|
26
26
|
OptionParser.new do |opts|
|
@@ -42,12 +42,14 @@ module Graticule
|
|
42
42
|
|
43
43
|
options[:location] = args.join(" ")
|
44
44
|
|
45
|
-
result = Graticule.service(options[:service]).new(options[:api_key]).locate(options[:location])
|
45
|
+
result = Graticule.service(options[:service]).new(*options[:api_key].split(',')).locate(options[:location])
|
46
46
|
location = (result.is_a?(Array) ? result.first : result)
|
47
47
|
if location
|
48
|
-
|
48
|
+
out << location.to_s(:coordinates => true)
|
49
|
+
exit 0
|
49
50
|
else
|
50
|
-
|
51
|
+
out << "Location not found"
|
52
|
+
exit 1
|
51
53
|
end
|
52
54
|
rescue Graticule::CredentialsError
|
53
55
|
$stderr.puts "Invalid API key. Pass your #{options[:service]} API key using the -a option. "
|
@@ -0,0 +1,112 @@
|
|
1
|
+
require 'open-uri'
|
2
|
+
|
3
|
+
module Graticule #:nodoc:
|
4
|
+
module Geocoder
|
5
|
+
|
6
|
+
# Abstract class for implementing geocoders.
|
7
|
+
#
|
8
|
+
# === Example
|
9
|
+
#
|
10
|
+
# The following methods must be implemented in sublcasses:
|
11
|
+
#
|
12
|
+
# * +initialize+:: Sets @url to the service enpoint.
|
13
|
+
# * +check_error+:: Checks for errors in the server response.
|
14
|
+
# * +parse_response+:: Extracts information from the server response.
|
15
|
+
#
|
16
|
+
# Optionally, you can also override
|
17
|
+
#
|
18
|
+
# * +prepare_response+:: Convert the string response into a different format
|
19
|
+
# that gets passed on to +check_error+ and +parse_response+.
|
20
|
+
#
|
21
|
+
# If you have extra URL paramaters (application id, output type) or need to
|
22
|
+
# perform URL customization, override +make_url+.
|
23
|
+
#
|
24
|
+
# class FakeGeocoder < Base
|
25
|
+
#
|
26
|
+
# def initialize(appid)
|
27
|
+
# @appid = appid
|
28
|
+
# @url = URI.parse 'http://example.com/test'
|
29
|
+
# end
|
30
|
+
#
|
31
|
+
# def locate(query)
|
32
|
+
# get :q => query
|
33
|
+
# end
|
34
|
+
#
|
35
|
+
# private
|
36
|
+
#
|
37
|
+
# def check_error(xml)
|
38
|
+
# raise Error, xml.elements['error'].text if xml.elements['error']
|
39
|
+
# end
|
40
|
+
#
|
41
|
+
# def make_url(params)
|
42
|
+
# params[:appid] = @appid
|
43
|
+
# super params
|
44
|
+
# end
|
45
|
+
#
|
46
|
+
# def parse_response(response)
|
47
|
+
# # return Location
|
48
|
+
# end
|
49
|
+
#
|
50
|
+
# end
|
51
|
+
#
|
52
|
+
class Base
|
53
|
+
USER_AGENT = "Mozilla/5.0 (compatible; Graticule/#{Graticule::Version::STRING}; http://graticule.rubyforge.org)"
|
54
|
+
|
55
|
+
def initialize
|
56
|
+
raise NotImplementedError
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
def location_from_params(params)
|
62
|
+
case params
|
63
|
+
when Location then params
|
64
|
+
when Hash then Location.new params
|
65
|
+
else
|
66
|
+
raise ArgumentError, "Expected a Graticule::Location or a hash with :street, :locality, :region, :postal_code, and :country attributes"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
# Check for errors in +response+ and raise appropriate error, if any.
|
71
|
+
# Must return if no error could be found.
|
72
|
+
def check_error(response)
|
73
|
+
raise NotImplementedError
|
74
|
+
end
|
75
|
+
|
76
|
+
# Performs a GET request with +params+. Calls +check_error+ and returns
|
77
|
+
# the result of +parse_response+.
|
78
|
+
def get(params = {})
|
79
|
+
response = prepare_response(make_url(params).open('User-Agent' => USER_AGENT).read)
|
80
|
+
check_error(response)
|
81
|
+
return parse_response(response)
|
82
|
+
rescue OpenURI::HTTPError => e
|
83
|
+
check_error(prepare_response(e.io.read))
|
84
|
+
raise
|
85
|
+
end
|
86
|
+
|
87
|
+
# Creates a URI from the Hash +params+. Override this then call super if
|
88
|
+
# you need to add extra params like an application id or output type.
|
89
|
+
def make_url(params)
|
90
|
+
escaped_params = params.sort_by { |k,v| k.to_s }.map do |k,v|
|
91
|
+
"#{URI.escape k.to_s}=#{URI.escape v.to_s}"
|
92
|
+
end
|
93
|
+
|
94
|
+
url = @url.dup
|
95
|
+
url.query = escaped_params.join '&'
|
96
|
+
return url
|
97
|
+
end
|
98
|
+
|
99
|
+
# Override to convert the response to something besides a String, which
|
100
|
+
# will get passed to +check_error+ and +parse_response+.
|
101
|
+
def prepare_response(response)
|
102
|
+
response
|
103
|
+
end
|
104
|
+
|
105
|
+
# Must parse results from +response+ into a Location.
|
106
|
+
def parse_response(response)
|
107
|
+
raise NotImplementedError
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
@@ -51,11 +51,11 @@ module Graticule #:nodoc:
|
|
51
51
|
longitude, latitude, = xml.elements['/kml/Response/Placemark/Point/coordinates'].text.split(',').map { |v| v.to_f }
|
52
52
|
|
53
53
|
Location.new \
|
54
|
-
:street => value(address.elements['
|
55
|
-
:locality => value(address.elements['
|
56
|
-
:region => value(address.elements['
|
57
|
-
:postal_code => value(address.elements['
|
58
|
-
:country => value(address.elements['
|
54
|
+
:street => value(address.elements['//ThoroughfareName/text()']),
|
55
|
+
:locality => value(address.elements['//LocalityName/text()']),
|
56
|
+
:region => value(address.elements['//AdministrativeAreaName/text()']),
|
57
|
+
:postal_code => value(address.elements['//PostalCodeNumber/text()']),
|
58
|
+
:country => value(address.elements['//CountryNameCode/text()']),
|
59
59
|
:latitude => latitude,
|
60
60
|
:longitude => longitude,
|
61
61
|
:precision => PRECISION[address.attribute('Accuracy').value.to_i] || :unknown
|
@@ -3,7 +3,7 @@ require 'yaml'
|
|
3
3
|
module Graticule #:nodoc:
|
4
4
|
module Geocoder #:nodoc:
|
5
5
|
|
6
|
-
class HostIp
|
6
|
+
class HostIp < Base
|
7
7
|
|
8
8
|
def initialize
|
9
9
|
@url = URI.parse 'http://api.hostip.info/get_html.php'
|
@@ -11,15 +11,15 @@ module Graticule #:nodoc:
|
|
11
11
|
|
12
12
|
# Geocode an IP address using http://hostip.info
|
13
13
|
def locate(address)
|
14
|
-
|
15
|
-
# add new line so YAML.load doesn't puke
|
16
|
-
result = response.read + "\n"
|
17
|
-
check_error(result)
|
18
|
-
parse_response(YAML.load(result))
|
19
|
-
end
|
14
|
+
get :ip => address, :position => true
|
20
15
|
end
|
21
16
|
|
22
17
|
private
|
18
|
+
|
19
|
+
def read_response(response)
|
20
|
+
# add new line so YAML.load doesn't puke
|
21
|
+
YAML.load(response + "\n")
|
22
|
+
end
|
23
23
|
|
24
24
|
def parse_response(response) #:nodoc:
|
25
25
|
returning Location.new do |location|
|
@@ -32,19 +32,10 @@ module Graticule #:nodoc:
|
|
32
32
|
end
|
33
33
|
|
34
34
|
def check_error(response) #:nodoc:
|
35
|
-
raise AddressError, 'Unknown' if response =~ /Unknown City/
|
36
|
-
raise AddressError, 'Private Address' if response =~ /Private Address/
|
35
|
+
raise AddressError, 'Unknown' if response['City'] =~ /Unknown City/
|
36
|
+
raise AddressError, 'Private Address' if response['City'] =~ /Private Address/
|
37
37
|
end
|
38
38
|
|
39
|
-
def make_url(params) #:nodoc:
|
40
|
-
returning @url.dup do |url|
|
41
|
-
url.query = params.map do |k,v|
|
42
|
-
"#{URI.escape k.to_s}=#{URI.escape v.to_s}"
|
43
|
-
end.join('&')
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
|
48
39
|
end
|
49
40
|
end
|
50
41
|
end
|
@@ -4,7 +4,7 @@ module Graticule #:nodoc:
|
|
4
4
|
# A library for lookup of coordinates with http://geo.localsearchmaps.com/
|
5
5
|
#
|
6
6
|
# See http://emad.fano.us/blog/?p=277
|
7
|
-
class LocalSearchMaps <
|
7
|
+
class LocalSearchMaps < Base
|
8
8
|
|
9
9
|
def initialize
|
10
10
|
@url = URI.parse 'http://geo.localsearchmaps.com/'
|
@@ -28,13 +28,13 @@ module Graticule #:nodoc:
|
|
28
28
|
end
|
29
29
|
|
30
30
|
def check_error(js)
|
31
|
-
raise AddressError, "Empty Response" if js.nil?
|
32
|
-
raise AddressError, 'Location not found' if js
|
31
|
+
raise AddressError, "Empty Response" if js.nil?
|
32
|
+
raise AddressError, 'Location not found' if js =~ /location not found/
|
33
33
|
end
|
34
34
|
|
35
35
|
def parse_response(js)
|
36
36
|
returning Location.new do |location|
|
37
|
-
coordinates = js.
|
37
|
+
coordinates = js.match(/map.centerAndZoom\(new GPoint\((.+?), (.+?)\)/)
|
38
38
|
location.longitude = coordinates[1].to_f
|
39
39
|
location.latitude = coordinates[2].to_f
|
40
40
|
end
|
@@ -13,7 +13,7 @@ module Graticule
|
|
13
13
|
|
14
14
|
# Finds +location+ and returns a Location object.
|
15
15
|
def locate(location)
|
16
|
-
get :q => location.is_a?(String) ? location : location_from_params(location).to_s
|
16
|
+
get :q => location.is_a?(String) ? location : location_from_params(location).to_s, :output => 'locations'
|
17
17
|
end
|
18
18
|
|
19
19
|
private
|
@@ -22,11 +22,6 @@ module Graticule
|
|
22
22
|
raise AddressError, 'bad location' unless xml.elements['Locations/Location']
|
23
23
|
end
|
24
24
|
|
25
|
-
def make_url(params) # :nodoc:
|
26
|
-
params[:output] = 'locations'
|
27
|
-
super params
|
28
|
-
end
|
29
|
-
|
30
25
|
def parse_response(xml) # :nodoc:
|
31
26
|
result = xml.elements['/Locations/Location[1]']
|
32
27
|
coords = result.elements['Centroid/gml:Point/gml:coordinates'].text.split ','
|
@@ -1,110 +1,18 @@
|
|
1
|
-
require 'open-uri'
|
2
1
|
require 'rexml/document'
|
3
2
|
|
4
3
|
module Graticule #:nodoc:
|
5
4
|
module Geocoder #:nodoc:
|
6
5
|
|
7
|
-
# Abstract class for implementing REST
|
8
|
-
#
|
9
|
-
|
10
|
-
#
|
11
|
-
# The following methods must be implemented in sublcasses:
|
12
|
-
#
|
13
|
-
# +initialize+:: Sets @url to the service enpoint.
|
14
|
-
# +check_error+:: Checks for errors in the server response.
|
15
|
-
# +parse_response+:: Extracts information from the server response.
|
16
|
-
#
|
17
|
-
# If you have extra URL paramaters (application id, output type) or need to
|
18
|
-
# perform URL customization, override +make_url+.
|
19
|
-
#
|
20
|
-
# class FakeService < RCRest
|
21
|
-
#
|
22
|
-
# class Error < RCRest::Error; end
|
23
|
-
#
|
24
|
-
# def initialize(appid)
|
25
|
-
# @appid = appid
|
26
|
-
# @url = URI.parse 'http://example.com/test'
|
27
|
-
# end
|
28
|
-
#
|
29
|
-
# def check_error(xml)
|
30
|
-
# raise Error, xml.elements['error'].text if xml.elements['error']
|
31
|
-
# end
|
32
|
-
#
|
33
|
-
# def make_url(params)
|
34
|
-
# params[:appid] = @appid
|
35
|
-
# super params
|
36
|
-
# end
|
37
|
-
#
|
38
|
-
# def parse_response(xml)
|
39
|
-
# # return Location
|
40
|
-
# end
|
41
|
-
#
|
42
|
-
# def test(query)
|
43
|
-
# get :q => query
|
44
|
-
# end
|
45
|
-
#
|
46
|
-
# end
|
47
|
-
class Rest
|
6
|
+
# Abstract class for implementing REST geocoders. Passes on a REXML::Document
|
7
|
+
# to +check_errors+ and +parse_response+.
|
8
|
+
class Rest < Base
|
48
9
|
|
49
|
-
# Web services initializer.
|
50
|
-
#
|
51
|
-
# Concrete web services implementations must set the +url+ instance
|
52
|
-
# variable which must be a URI.
|
53
|
-
def initialize
|
54
|
-
raise NotImplementedError
|
55
|
-
end
|
56
|
-
|
57
10
|
private
|
58
11
|
|
59
|
-
def
|
60
|
-
|
61
|
-
when Location then params
|
62
|
-
when Hash then Location.new params
|
63
|
-
else
|
64
|
-
raise ArgumentError, "Expected a Graticule::Location or a hash with :street, :locality, :region, :postal_code, and :country attributes"
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
# Must extract and raise an error from +xml+, an REXML::Document, if any.
|
69
|
-
# Must returns if no error could be found.
|
70
|
-
def check_error(xml)
|
71
|
-
raise NotImplementedError
|
72
|
-
end
|
73
|
-
|
74
|
-
# Performs a GET request with +params+. Calls the parse_response method on
|
75
|
-
# the concrete class with an REXML::Document instance and returns its
|
76
|
-
# result.
|
77
|
-
def get(params = {})
|
78
|
-
url = make_url params
|
79
|
-
|
80
|
-
url.open do |response|
|
81
|
-
res = REXML::Document.new response.read
|
82
|
-
check_error(res)
|
83
|
-
return parse_response(res)
|
84
|
-
end
|
85
|
-
rescue OpenURI::HTTPError => e
|
86
|
-
response = REXML::Document.new e.io.read
|
87
|
-
check_error response
|
88
|
-
raise
|
12
|
+
def prepare_response(response)
|
13
|
+
REXML::Document.new(response)
|
89
14
|
end
|
90
|
-
|
91
|
-
# Creates a URI from the Hash +params+. Override this then call super if
|
92
|
-
# you need to add extra params like an application id or output type.
|
93
|
-
def make_url(params)
|
94
|
-
escaped_params = params.sort_by { |k,v| k.to_s }.map do |k,v|
|
95
|
-
"#{URI.escape k.to_s}=#{URI.escape v.to_s}"
|
96
|
-
end
|
97
|
-
|
98
|
-
url = @url.dup
|
99
|
-
url.query = escaped_params.join '&'
|
100
|
-
return url
|
101
|
-
end
|
102
|
-
|
103
|
-
# Must parse results from +xml+, an REXML::Document, into a Location.
|
104
|
-
def parse_response(xml)
|
105
|
-
raise NotImplementedError
|
106
|
-
end
|
107
|
-
|
15
|
+
|
108
16
|
end
|
109
17
|
end
|
110
18
|
end
|