graticule 0.2.2 → 0.2.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|