GUI-graticule 0.2.7.2
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.txt +46 -0
- data/LICENSE.txt +30 -0
- data/Manifest.txt +73 -0
- data/README.txt +29 -0
- data/Rakefile +86 -0
- data/bin/geocode +5 -0
- data/init.rb +2 -0
- data/lib/graticule.rb +26 -0
- data/lib/graticule/cli.rb +64 -0
- data/lib/graticule/distance.rb +29 -0
- data/lib/graticule/distance/haversine.rb +40 -0
- data/lib/graticule/distance/spherical.rb +52 -0
- data/lib/graticule/distance/vincenty.rb +76 -0
- data/lib/graticule/geocoder.rb +21 -0
- data/lib/graticule/geocoder/base.rb +138 -0
- data/lib/graticule/geocoder/bogus.rb +15 -0
- data/lib/graticule/geocoder/geocoder_ca.rb +54 -0
- data/lib/graticule/geocoder/geocoder_us.rb +49 -0
- data/lib/graticule/geocoder/google.rb +122 -0
- data/lib/graticule/geocoder/host_ip.rb +41 -0
- data/lib/graticule/geocoder/local_search_maps.rb +45 -0
- data/lib/graticule/geocoder/map_quest.rb +111 -0
- data/lib/graticule/geocoder/meta_carta.rb +33 -0
- data/lib/graticule/geocoder/multi.rb +80 -0
- data/lib/graticule/geocoder/postcode_anywhere.rb +63 -0
- data/lib/graticule/geocoder/rest.rb +18 -0
- data/lib/graticule/geocoder/yahoo.rb +102 -0
- data/lib/graticule/location.rb +488 -0
- data/lib/graticule/version.rb +9 -0
- 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 +18 -0
- data/test/fixtures/responses/geocoder_us/unknown.xml +1 -0
- data/test/fixtures/responses/google/badkey.xml +1 -0
- data/test/fixtures/responses/google/limit.xml +10 -0
- data/test/fixtures/responses/google/missing_address.xml +1 -0
- data/test/fixtures/responses/google/only_coordinates.xml +1 -0
- data/test/fixtures/responses/google/partial.xml +1 -0
- data/test/fixtures/responses/google/server_error.xml +10 -0
- data/test/fixtures/responses/google/success.xml +1 -0
- data/test/fixtures/responses/google/unavailable.xml +1 -0
- data/test/fixtures/responses/google/unknown_address.xml +1 -0
- data/test/fixtures/responses/host_ip/private.txt +4 -0
- data/test/fixtures/responses/host_ip/success.txt +4 -0
- data/test/fixtures/responses/host_ip/unknown.txt +4 -0
- 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 -0
- data/test/fixtures/responses/meta_carta/bad_address.xml +17 -0
- data/test/fixtures/responses/meta_carta/multiple.xml +33 -0
- data/test/fixtures/responses/meta_carta/success.xml +31 -0
- data/test/fixtures/responses/postcode_anywhere/badkey.xml +9 -0
- data/test/fixtures/responses/postcode_anywhere/canada.xml +16 -0
- data/test/fixtures/responses/postcode_anywhere/empty.xml +16 -0
- data/test/fixtures/responses/postcode_anywhere/success.xml +16 -0
- data/test/fixtures/responses/postcode_anywhere/uk.xml +18 -0
- data/test/fixtures/responses/yahoo/success.xml +3 -0
- data/test/fixtures/responses/yahoo/unknown_address.xml +6 -0
- data/test/mocks/uri.rb +52 -0
- data/test/test_helper.rb +32 -0
- data/test/unit/graticule/distance_test.rb +58 -0
- data/test/unit/graticule/geocoder/geocoder_us_test.rb +43 -0
- data/test/unit/graticule/geocoder/google_test.rb +126 -0
- data/test/unit/graticule/geocoder/host_ip_test.rb +40 -0
- data/test/unit/graticule/geocoder/local_search_maps_test.rb +30 -0
- data/test/unit/graticule/geocoder/meta_carta_test.rb +44 -0
- data/test/unit/graticule/geocoder/multi_test.rb +43 -0
- data/test/unit/graticule/geocoder/postcode_anywhere_test.rb +50 -0
- data/test/unit/graticule/geocoder/yahoo_test.rb +58 -0
- data/test/unit/graticule/geocoder_test.rb +27 -0
- data/test/unit/graticule/location_test.rb +66 -0
- metadata +158 -0
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
module Graticule #:nodoc:
|
4
|
+
module Geocoder #:nodoc:
|
5
|
+
|
6
|
+
class HostIp < Base
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@url = URI.parse 'http://api.hostip.info/get_html.php'
|
10
|
+
end
|
11
|
+
|
12
|
+
# Geocode an IP address using http://hostip.info
|
13
|
+
def locate(address)
|
14
|
+
get :ip => address, :position => true
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def prepare_response(response)
|
20
|
+
# add new line so YAML.load doesn't puke
|
21
|
+
YAML.load(response + "\n")
|
22
|
+
end
|
23
|
+
|
24
|
+
def parse_response(parse_type, response) #:nodoc:
|
25
|
+
returning Location.new do |location|
|
26
|
+
location.latitude = response['Latitude']
|
27
|
+
location.longitude = response['Longitude']
|
28
|
+
location.locality, location.region = response['City'].split(', ')
|
29
|
+
country = response['Country'].match(/\((\w+)\)$/)
|
30
|
+
location.country = country[1] if country
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def check_error(response) #:nodoc:
|
35
|
+
raise AddressError, 'Unknown' if response['City'] =~ /Unknown City/
|
36
|
+
raise AddressError, 'Private Address' if response['City'] =~ /Private Address/
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Graticule #:nodoc:
|
2
|
+
module Geocoder #:nodoc:
|
3
|
+
|
4
|
+
# A library for lookup of coordinates with http://geo.localsearchmaps.com/
|
5
|
+
#
|
6
|
+
# See http://emad.fano.us/blog/?p=277
|
7
|
+
class LocalSearchMaps < Base
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@url = URI.parse 'http://geo.localsearchmaps.com/'
|
11
|
+
end
|
12
|
+
|
13
|
+
# This web service will handle some addresses outside the US
|
14
|
+
# if given more structured arguments than just a string address
|
15
|
+
# So allow input as a hash for the different arguments (:city, :country, :zip)
|
16
|
+
def locate(params)
|
17
|
+
get params.is_a?(String) ? {:loc => params} : map_attributes(location_from_params(params))
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def map_attributes(location)
|
23
|
+
mapping = {:street => :street, :locality => :city, :region => :state, :postal_code => :zip, :country => :country}
|
24
|
+
mapping.keys.inject({}) do |result,attribute|
|
25
|
+
result[mapping[attribute]] = location.attributes[attribute] unless location.attributes[attribute].blank?
|
26
|
+
result
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def check_error(js)
|
31
|
+
raise AddressError, "Empty Response" if js.nil?
|
32
|
+
raise AddressError, 'Location not found' if js =~ /location not found/
|
33
|
+
end
|
34
|
+
|
35
|
+
def parse_response(parse_type, js)
|
36
|
+
returning Location.new do |location|
|
37
|
+
coordinates = js.match(/map.centerAndZoom\(new GPoint\((.+?), (.+?)\)/)
|
38
|
+
location.longitude = coordinates[1].to_f
|
39
|
+
location.latitude = coordinates[2].to_f
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
module Graticule #:nodoc:
|
2
|
+
module Geocoder #:nodoc:
|
3
|
+
|
4
|
+
# First you need a Mapquest API key. You can register for one here:
|
5
|
+
# http://www.mapquest.com/features/main.adp?page=developer_tools_oapi
|
6
|
+
#
|
7
|
+
# Then you create a MapquestGeocode object and start locating addresses:
|
8
|
+
#
|
9
|
+
# gg = Graticule.service(:map_quest).new(MAPS_API_KEY)
|
10
|
+
# location = gg.locate :street => '1600 Amphitheater Pkwy', :locality => 'Mountain View', :region => 'CA'
|
11
|
+
# p location.coordinates
|
12
|
+
#
|
13
|
+
class MapQuest < Rest
|
14
|
+
# http://trc.mapquest.com
|
15
|
+
|
16
|
+
PRECISION = {
|
17
|
+
0 => Precision.unknown,
|
18
|
+
'COUNTRY' => Precision.country,
|
19
|
+
'STATE' => Precision.state,
|
20
|
+
'COUNTY' => Precision.state,
|
21
|
+
'CITY' => Precision.city,
|
22
|
+
'ZIP' => Precision.zip,
|
23
|
+
'ZIP7' => Precision.zip,
|
24
|
+
'ZIP9' => Precision.zip,
|
25
|
+
'INTERSECTIONS' => Precision.street,
|
26
|
+
'STREET' => Precision.street,
|
27
|
+
'ADDRESS' => Precision.address
|
28
|
+
}
|
29
|
+
|
30
|
+
# Creates a new MapquestGeocode that will use Mapquest API key +key+.
|
31
|
+
#
|
32
|
+
# WARNING: The MapQuest API Keys tend to be already URI encoded. If this is the case
|
33
|
+
# be sure to URI.unescape the key in the call to new
|
34
|
+
def initialize(key)
|
35
|
+
@key = key
|
36
|
+
@url = URI.parse 'http://web.openapi.mapquest.com/oapi/transaction'
|
37
|
+
end
|
38
|
+
|
39
|
+
# Locates +address+ returning a Location
|
40
|
+
def locate(address)
|
41
|
+
get map_attributes(location_from_params(address))
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def map_attributes(location)
|
47
|
+
mapping = {:street => :address, :locality => :city, :region => :stateProvince, :postal_code => :postalcoe, :country => :country}
|
48
|
+
mapping.keys.inject({}) do |result,attribute|
|
49
|
+
result[mapping[attribute]] = location.attributes[attribute] unless location.attributes[attribute].blank?
|
50
|
+
result
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# Extracts a Location from +xml+.
|
55
|
+
def parse_response(parse_type, xml) #:nodoc:
|
56
|
+
address = REXML::XPath.first(xml, '/advantage/geocode/locations/location')
|
57
|
+
|
58
|
+
Location.new \
|
59
|
+
:street => value(address.elements['//address/text()']),
|
60
|
+
:locality => value(address.elements['//city/text()']),
|
61
|
+
:region => value(address.elements['//stateProvince/text()']),
|
62
|
+
:postal_code => value(address.elements['//postalCode/text()']),
|
63
|
+
:country => value(address.elements['//country/text()']),
|
64
|
+
:latitude => value(address.elements['//latitude/text()']),
|
65
|
+
:longitude => value(address.elements['//longitude/text()']),
|
66
|
+
:precision => PRECISION[address.elements['//geocodeQuality'].text] || :unknown
|
67
|
+
end
|
68
|
+
|
69
|
+
# Extracts and raises an error from +xml+, if any.
|
70
|
+
def check_error(xml) #:nodoc:
|
71
|
+
return unless xml.elements['//error']
|
72
|
+
status = xml.elements['//error/code'].text.to_i
|
73
|
+
msg = xml.elements['//error/text'].text
|
74
|
+
case status
|
75
|
+
when 255..299 then
|
76
|
+
raise CredentialsError, msg
|
77
|
+
when 400..500 then
|
78
|
+
raise AddressError, msg
|
79
|
+
when 600.699 then
|
80
|
+
raise Error, msg
|
81
|
+
when 900 then
|
82
|
+
raise AddressError, 'invalid latitude'
|
83
|
+
when 901 then
|
84
|
+
raise AddressError, 'invalid longitude'
|
85
|
+
when 902 then
|
86
|
+
raise AddressError, 'error parsing params'
|
87
|
+
when 9902 then
|
88
|
+
raise CredentialsError, 'invalid key'
|
89
|
+
when 9904 then
|
90
|
+
raise CredentialsError, 'key missing'
|
91
|
+
else
|
92
|
+
raise Error, "unknown error #{status}: #{msg}"
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
# Creates a URL from the Hash +params+. Automatically adds the key and
|
97
|
+
# sets the output type to 'xml'.
|
98
|
+
def make_url(params) #:nodoc:
|
99
|
+
super params.merge({:key => @key, :transaction => 'geocode', :ambiguities => 0})
|
100
|
+
end
|
101
|
+
|
102
|
+
def value(element)
|
103
|
+
element.value if element
|
104
|
+
end
|
105
|
+
|
106
|
+
def text(element)
|
107
|
+
element.text if element
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
|
2
|
+
module Graticule
|
3
|
+
module Geocoder
|
4
|
+
|
5
|
+
# Library for looking up coordinates with MetaCarta's GeoParser API.
|
6
|
+
#
|
7
|
+
# http://labs.metacarta.com/GeoParser/documentation.html
|
8
|
+
class MetaCarta < Rest
|
9
|
+
|
10
|
+
def initialize # :nodoc:
|
11
|
+
@url = URI.parse 'http://labs.metacarta.com/GeoParser/'
|
12
|
+
end
|
13
|
+
|
14
|
+
# Finds +location+ and returns a Location object.
|
15
|
+
def locate(location)
|
16
|
+
get :q => location.is_a?(String) ? location : location_from_params(location).to_s, :output => 'locations'
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def check_error(xml) # :nodoc:
|
22
|
+
raise AddressError, 'bad location' unless xml.elements['Locations/Location']
|
23
|
+
end
|
24
|
+
|
25
|
+
def parse_response(parse_type, xml) # :nodoc:
|
26
|
+
result = xml.elements['/Locations/Location[1]']
|
27
|
+
coords = result.elements['Centroid/gml:Point/gml:coordinates'].text.split ','
|
28
|
+
Location.new :latitude => coords.first.to_f, :longitude => coords.last.to_f
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
module Graticule #:nodoc:
|
2
|
+
module Geocoder #:nodoc:
|
3
|
+
class Multi
|
4
|
+
|
5
|
+
# The Multi geocoder allows you to use multiple geocoders in succession.
|
6
|
+
#
|
7
|
+
# geocoder = Graticule.service(:multi).new(
|
8
|
+
# Graticule.service(:google).new("api_key"),
|
9
|
+
# Graticule.service(:yahoo).new("api_key"),
|
10
|
+
# )
|
11
|
+
# geocoder.locate '49423' # <= tries geocoders in succession
|
12
|
+
#
|
13
|
+
# The Multi geocoder will try the geocoders in order if a Graticule::AddressError
|
14
|
+
# is raised. You can customize this behavior by passing in a block to the Multi
|
15
|
+
# geocoder. For example, to try the geocoders until one returns a result with a
|
16
|
+
# high enough precision:
|
17
|
+
#
|
18
|
+
# geocoder = Graticule.service(:multi).new(geocoders) do |result|
|
19
|
+
# result.precision >= Graticule::Precision.street
|
20
|
+
# end
|
21
|
+
#
|
22
|
+
# Geocoders will be tried in order until the block returned true for one of the results
|
23
|
+
#
|
24
|
+
def initialize(*geocoders, &acceptable)
|
25
|
+
@acceptable = acceptable || lambda { true }
|
26
|
+
@geocoders = geocoders.flatten
|
27
|
+
end
|
28
|
+
|
29
|
+
def locate(*args)
|
30
|
+
mode, address = nil, nil
|
31
|
+
case args.first
|
32
|
+
when :first
|
33
|
+
mode = :first
|
34
|
+
address = args[1]
|
35
|
+
when :all
|
36
|
+
mode = :all
|
37
|
+
address = args[1]
|
38
|
+
else
|
39
|
+
mode = :first
|
40
|
+
address = args.first
|
41
|
+
end
|
42
|
+
|
43
|
+
locations = Locations.new
|
44
|
+
last_error = nil
|
45
|
+
|
46
|
+
catch :found_first do
|
47
|
+
@geocoders.each do |geocoder|
|
48
|
+
begin
|
49
|
+
geocoder_locations = geocoder.locate(:all, address)
|
50
|
+
|
51
|
+
geocoder_locations.each do |location|
|
52
|
+
if(@acceptable.call(location))
|
53
|
+
locations << location
|
54
|
+
|
55
|
+
if(mode == :first)
|
56
|
+
throw :found_first
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
rescue Errno::ECONNREFUSED
|
61
|
+
logger.error("Connection refused to #{service}")
|
62
|
+
rescue Error => e
|
63
|
+
last_error = e
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
if(mode == :first)
|
69
|
+
if(locations.first)
|
70
|
+
locations.first
|
71
|
+
else
|
72
|
+
raise last_error || AddressError.new("Couldn't find '#{address}' with any of the services")
|
73
|
+
end
|
74
|
+
else
|
75
|
+
locations
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module Graticule #:nodoc:
|
2
|
+
module Geocoder #:nodoc:
|
3
|
+
|
4
|
+
class PostcodeAnywhere < Rest
|
5
|
+
|
6
|
+
# http://www.postcodeanywhere.com/register/
|
7
|
+
def initialize(account_code, license_code)
|
8
|
+
@url = URI.parse 'http://services.postcodeanywhere.co.uk/xml.aspx'
|
9
|
+
@account_code = account_code
|
10
|
+
@license_code = license_code
|
11
|
+
end
|
12
|
+
|
13
|
+
def locate(params)
|
14
|
+
location = location_from_params(params)
|
15
|
+
get :address => location.to_s(:country => false), :country => location.country
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def make_url(params) #:nodoc:
|
21
|
+
params[:account_code] = @account_code
|
22
|
+
params[:license_code] = @license_code
|
23
|
+
params[:action] = 'geocode'
|
24
|
+
super params
|
25
|
+
end
|
26
|
+
|
27
|
+
def parse_response(parse_type, xml) #:nodoc:
|
28
|
+
result = xml.elements['/PostcodeAnywhere/Data/Item[1]']
|
29
|
+
returning Location.new do |location|
|
30
|
+
location.latitude = result.attribute('latitude').value.to_f
|
31
|
+
location.longitude = result.attribute('longitude').value.to_f
|
32
|
+
location.street = value(result.attribute('line1'))
|
33
|
+
location.locality = value(result.attribute('city'))
|
34
|
+
location.region = value(result.attribute('state'))
|
35
|
+
location.postal_code = value(result.attribute('postal_code'))
|
36
|
+
location.country = value(result.attribute('country'))
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def value(attribute)
|
41
|
+
attribute.value if attribute
|
42
|
+
end
|
43
|
+
|
44
|
+
# http://www.postcodeanywhere.co.uk/developers/documentation/errors.aspx
|
45
|
+
def check_error(xml) #:nodoc:
|
46
|
+
#raise AddressError, xml.text if xml.text == 'couldn\'t find this address! sorry'
|
47
|
+
if error = xml.elements['/PostcodeAnywhere/Data/Item[@error_number][1]']
|
48
|
+
error_number = error.attribute('error_number').value.to_i
|
49
|
+
message = error.attribute('message').value
|
50
|
+
if (1..11).include?(error_number) || (34..38).include?(error_number)
|
51
|
+
raise CredentialsError, message
|
52
|
+
else
|
53
|
+
raise Error, message
|
54
|
+
end
|
55
|
+
elsif xml.elements['/PostcodeAnywhere/Data'].elements.empty?
|
56
|
+
raise AddressError, 'No results returned'
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'rexml/document'
|
2
|
+
|
3
|
+
module Graticule #:nodoc:
|
4
|
+
module Geocoder #:nodoc:
|
5
|
+
|
6
|
+
# Abstract class for implementing REST geocoders. Passes on a REXML::Document
|
7
|
+
# to +check_errors+ and +parse_response+.
|
8
|
+
class Rest < Base
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def prepare_response(response)
|
13
|
+
REXML::Document.new(response)
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
module Graticule #:nodoc:
|
2
|
+
module Geocoder #:nodoc:
|
3
|
+
|
4
|
+
# Yahoo geocoding API.
|
5
|
+
#
|
6
|
+
# http://developer.yahoo.com/maps/rest/V1/geocode.html
|
7
|
+
class Yahoo < Rest
|
8
|
+
|
9
|
+
PRECISION = {
|
10
|
+
"country"=> Precision.country,
|
11
|
+
"state" => Precision.state,
|
12
|
+
"city" => Precision.city,
|
13
|
+
"zip+4" => Precision.zip,
|
14
|
+
"zip+2" => Precision.zip,
|
15
|
+
"zip" => Precision.zip,
|
16
|
+
"street" => Precision.street,
|
17
|
+
"address" => Precision.address
|
18
|
+
}
|
19
|
+
|
20
|
+
# Web services initializer.
|
21
|
+
#
|
22
|
+
# The +appid+ is the Application ID that uniquely identifies your
|
23
|
+
# application. See: http://developer.yahoo.com/faq/index.html#appid
|
24
|
+
#
|
25
|
+
# See http://developer.yahoo.com/search/rest.html
|
26
|
+
def initialize(appid)
|
27
|
+
@appid = appid
|
28
|
+
@url = URI.parse "http://api.local.yahoo.com/MapsService/V1/geocode"
|
29
|
+
end
|
30
|
+
|
31
|
+
# Returns a Location for +address+.
|
32
|
+
#
|
33
|
+
# The +address+ can be any of:
|
34
|
+
# * city, state
|
35
|
+
# * city, state, zip
|
36
|
+
# * zip
|
37
|
+
# * street, city, state
|
38
|
+
# * street, city, state, zip
|
39
|
+
# * street, zip
|
40
|
+
def locate(*args)
|
41
|
+
case args.first
|
42
|
+
when :first then get :first, :location => extract_location(args[1])
|
43
|
+
when :all then get :all, :location => extract_location(args[1])
|
44
|
+
else get :first, :location => extract_location(args.first)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def extract_location(address)
|
49
|
+
location = (address.is_a?(String) ? address : location_from_params(address).to_s(:country => false))
|
50
|
+
# yahoo pukes on line breaks
|
51
|
+
location.gsub("\n", ', ')
|
52
|
+
end
|
53
|
+
|
54
|
+
def parse_response(parse_type, xml)
|
55
|
+
if parse_type == :all
|
56
|
+
locations = []
|
57
|
+
xml.elements['ResultSet'].each do |element|
|
58
|
+
locations << parse_location_xml(element)
|
59
|
+
end
|
60
|
+
return locations
|
61
|
+
else
|
62
|
+
return parse_location_xml(xml.elements['ResultSet/Result[1]'])
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def parse_location_xml(element)
|
67
|
+
returning Location.new do |location|
|
68
|
+
location.precision = PRECISION[element.attributes['precision']] || Precision.unknown
|
69
|
+
|
70
|
+
if element.attributes.include? 'warning' then
|
71
|
+
location.warning = element.attributes['warning']
|
72
|
+
end
|
73
|
+
location.latitude = element.elements['Latitude'].text.to_f
|
74
|
+
location.longitude = element.elements['Longitude'].text.to_f
|
75
|
+
|
76
|
+
location.street = element.elements['Address'].text unless element.elements['Address'].text.blank?
|
77
|
+
location.locality = element.elements['City'].text unless element.elements['City'].text.blank?
|
78
|
+
location.region = element.elements['State'].text
|
79
|
+
location.postal_code = element.elements['Zip'].text
|
80
|
+
location.country = element.elements['Country'].text
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
# Extracts and raises an error from +xml+, if any.
|
85
|
+
def check_error(xml) #:nodoc:
|
86
|
+
err = xml.elements['Error']
|
87
|
+
raise Error, err.elements['Message'].text if err
|
88
|
+
end
|
89
|
+
|
90
|
+
# Creates a URL from the Hash +params+. Automatically adds the appid and
|
91
|
+
# sets the output type to 'xml'.
|
92
|
+
def make_url(params) #:nodoc:
|
93
|
+
params[:appid] = @appid
|
94
|
+
params[:output] = 'xml'
|
95
|
+
|
96
|
+
super params
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
102
|
+
end
|