google-geocode 1.0.0
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/LICENSE +27 -0
- data/Manifest.txt +7 -0
- data/README +35 -0
- data/Rakefile +66 -0
- data/lib/google_geocode.rb +123 -0
- data/test/test_google_geocode.rb +74 -0
- data/test/uri_stub.rb +17 -0
- metadata +52 -0
data/LICENSE
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
Copyright 2006 Eric Hodel, The Robot Co-op. All rights reserved.
|
2
|
+
|
3
|
+
Redistribution and use in source and binary forms, with or without
|
4
|
+
modification, are permitted provided that the following conditions
|
5
|
+
are met:
|
6
|
+
|
7
|
+
1. Redistributions of source code must retain the above copyright
|
8
|
+
notice, this list of conditions and the following disclaimer.
|
9
|
+
2. Redistributions in binary form must reproduce the above copyright
|
10
|
+
notice, this list of conditions and the following disclaimer in the
|
11
|
+
documentation and/or other materials provided with the distribution.
|
12
|
+
3. Neither the names of the authors nor the names of their contributors
|
13
|
+
may be used to endorse or promote products derived from this software
|
14
|
+
without specific prior written permission.
|
15
|
+
|
16
|
+
THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
|
17
|
+
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
18
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
19
|
+
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
|
20
|
+
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
21
|
+
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
22
|
+
OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
23
|
+
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
24
|
+
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
25
|
+
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
26
|
+
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
27
|
+
|
data/Manifest.txt
ADDED
data/README
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
= google-geocode
|
2
|
+
|
3
|
+
Rubyforge Project:
|
4
|
+
|
5
|
+
http://rubyforge.org/projects/rctools
|
6
|
+
|
7
|
+
Documentation:
|
8
|
+
|
9
|
+
http://dev.robotcoop.com/Libraries/google-geocode
|
10
|
+
|
11
|
+
== About
|
12
|
+
|
13
|
+
google-geocode implements Google's Geocoding API.
|
14
|
+
|
15
|
+
== Installing google-geocode
|
16
|
+
|
17
|
+
Just install the gem:
|
18
|
+
|
19
|
+
$ sudo gem install google-geocode
|
20
|
+
|
21
|
+
== Using google-geocode
|
22
|
+
|
23
|
+
First you need a Google Maps API key. Yuo can register for one here:
|
24
|
+
|
25
|
+
http://www.google.com/apis/maps/signup.html
|
26
|
+
|
27
|
+
Then you create a GoogleGeocode object and start locating addresses:
|
28
|
+
|
29
|
+
require 'rubygems'
|
30
|
+
require 'google_geocode'
|
31
|
+
|
32
|
+
gg = GoogleGeocode.new application_id
|
33
|
+
location = gg.locate '1600 Amphitheater Pkwy, Mountain View, CA'
|
34
|
+
p location.coordinates
|
35
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
require 'rake/testtask'
|
4
|
+
require 'rake/rdoctask'
|
5
|
+
require 'rake/gempackagetask'
|
6
|
+
|
7
|
+
$VERBOSE = nil
|
8
|
+
|
9
|
+
spec = Gem::Specification.new do |s|
|
10
|
+
s.name = 'google-geocode'
|
11
|
+
s.version = '1.0.0'
|
12
|
+
s.summary = 'Google Geocoder API Library'
|
13
|
+
s.description = 'Map addresses to latitude and longitude with Google\'s Geocoder.'
|
14
|
+
s.author = 'Eric Hodel'
|
15
|
+
s.email = 'eric@robotcoop.com'
|
16
|
+
|
17
|
+
s.has_rdoc = true
|
18
|
+
s.files = File.read('Manifest.txt').split($/)
|
19
|
+
s.require_path = 'lib'
|
20
|
+
end
|
21
|
+
|
22
|
+
desc 'Run tests'
|
23
|
+
task :default => [ :test ]
|
24
|
+
|
25
|
+
Rake::TestTask.new('test') do |t|
|
26
|
+
t.libs << 'test'
|
27
|
+
t.pattern = 'test/test_*.rb'
|
28
|
+
t.verbose = true
|
29
|
+
end
|
30
|
+
|
31
|
+
desc 'Update Manifest.txt'
|
32
|
+
task :update_manifest do
|
33
|
+
sh "find . -type f | sed -e 's%./%%' | egrep -v 'svn|swp|~' | egrep -v '^(doc|pkg)/' | sort > Manifest.txt"
|
34
|
+
end
|
35
|
+
|
36
|
+
desc 'Generate RDoc'
|
37
|
+
Rake::RDocTask.new :rdoc do |rd|
|
38
|
+
rd.rdoc_dir = 'doc'
|
39
|
+
rd.rdoc_files.add 'lib', 'README', 'LICENSE'
|
40
|
+
rd.main = 'README'
|
41
|
+
rd.options << '-d' if `which dot` =~ /\/dot/
|
42
|
+
rd.options << '-t Google Geocode'
|
43
|
+
end
|
44
|
+
|
45
|
+
desc 'Generate RDoc for dev.robotcoop.com'
|
46
|
+
Rake::RDocTask.new :dev_rdoc do |rd|
|
47
|
+
rd.rdoc_dir = '../../../www/trunk/dev/html/Libraries/google-geocode'
|
48
|
+
rd.rdoc_files.add 'lib', 'README', 'LICENSE'
|
49
|
+
rd.main = 'README'
|
50
|
+
rd.options << '-d' if `which dot` =~ /\/dot/
|
51
|
+
rd.options << '-t Google Geocode'
|
52
|
+
end
|
53
|
+
|
54
|
+
desc 'Build Gem'
|
55
|
+
Rake::GemPackageTask.new spec do |pkg|
|
56
|
+
pkg.need_tar = true
|
57
|
+
end
|
58
|
+
|
59
|
+
desc 'Clean up'
|
60
|
+
task :clean => [ :clobber_rdoc, :clobber_package ]
|
61
|
+
|
62
|
+
desc 'Clean up'
|
63
|
+
task :clobber => [ :clean ]
|
64
|
+
|
65
|
+
# vim: syntax=Ruby
|
66
|
+
|
@@ -0,0 +1,123 @@
|
|
1
|
+
require 'open-uri'
|
2
|
+
require 'rexml/document'
|
3
|
+
|
4
|
+
##
|
5
|
+
# Library for looking up coordinates with Google's Geocoding API.
|
6
|
+
#
|
7
|
+
# http://www.google.com/apis/maps/documentation/#Geocoding_HTTP_Request
|
8
|
+
|
9
|
+
class GoogleGeocode
|
10
|
+
|
11
|
+
##
|
12
|
+
# Base error class
|
13
|
+
|
14
|
+
class Error < RuntimeError; end
|
15
|
+
|
16
|
+
##
|
17
|
+
# Raised when you try to locate an invalid address.
|
18
|
+
|
19
|
+
class AddressError < Error; end
|
20
|
+
|
21
|
+
##
|
22
|
+
# Raised when you use an invalid key.
|
23
|
+
|
24
|
+
class KeyError < Error; end
|
25
|
+
|
26
|
+
##
|
27
|
+
# Location struct
|
28
|
+
|
29
|
+
Location = Struct.new :address, :latitude, :longitude
|
30
|
+
|
31
|
+
##
|
32
|
+
# Creates a new GoogleGeocode that will use Google Maps API key +key+. You
|
33
|
+
# can sign up for an API key here:
|
34
|
+
#
|
35
|
+
# http://www.google.com/apis/maps/signup.html
|
36
|
+
|
37
|
+
def initialize(key)
|
38
|
+
@key = key
|
39
|
+
@url = URI.parse 'http://maps.google.com/maps/geo'
|
40
|
+
end
|
41
|
+
|
42
|
+
##
|
43
|
+
# Locates +address+ returning a Location struct.
|
44
|
+
|
45
|
+
def locate(address)
|
46
|
+
get :q => address
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def parse_response(xml)
|
52
|
+
l = Location.new
|
53
|
+
|
54
|
+
l.address = xml.elements['/kml/Response/Placemark/address'].text
|
55
|
+
|
56
|
+
coordinates = xml.elements['/kml/Response/Placemark/Point/coordinates'].text
|
57
|
+
l.longitude, l.latitude, = coordinates.split(',').map { |v| v.to_f }
|
58
|
+
|
59
|
+
return l
|
60
|
+
end
|
61
|
+
|
62
|
+
def check_error(obj)
|
63
|
+
obj = REXML::Document.new obj.read unless REXML::Document === obj
|
64
|
+
|
65
|
+
status = obj.elements['/kml/Response/Status/code'].text.to_i
|
66
|
+
case status
|
67
|
+
when 200 # ignore, ok
|
68
|
+
when 602
|
69
|
+
raise AddressError, 'invalid address'
|
70
|
+
when 610
|
71
|
+
raise KeyError, 'invalid key'
|
72
|
+
else
|
73
|
+
raise Error, "unknown error #{status}"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def get(params)
|
78
|
+
url = make_url params
|
79
|
+
|
80
|
+
url.open do |xml|
|
81
|
+
res = REXML::Document.new xml.read
|
82
|
+
|
83
|
+
check_error res
|
84
|
+
return parse_response(res)
|
85
|
+
end
|
86
|
+
rescue OpenURI::HTTPError => e
|
87
|
+
check_error e.io
|
88
|
+
raise
|
89
|
+
end
|
90
|
+
|
91
|
+
def make_url(params)
|
92
|
+
params[:key] = @key
|
93
|
+
params[:output] = 'xml'
|
94
|
+
|
95
|
+
escaped_params = params.sort_by { |k,v| k.to_s }.map do |k,v|
|
96
|
+
"#{URI.escape k.to_s}=#{URI.escape v.to_s}"
|
97
|
+
end
|
98
|
+
|
99
|
+
url = @url.dup
|
100
|
+
url.query = escaped_params.join '&'
|
101
|
+
return url
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
105
|
+
|
106
|
+
##
|
107
|
+
# A Location contains the following fields:
|
108
|
+
#
|
109
|
+
# +latitude+:: Latitude of the location
|
110
|
+
# +longitude+:: Longitude of the location
|
111
|
+
# +address+:: Street address of the result.
|
112
|
+
|
113
|
+
class GoogleGeocode::Location
|
114
|
+
|
115
|
+
##
|
116
|
+
# The coordinates for this location.
|
117
|
+
|
118
|
+
def coordinates
|
119
|
+
[latitude, longitude]
|
120
|
+
end
|
121
|
+
|
122
|
+
end
|
123
|
+
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'test/uri_stub'
|
3
|
+
|
4
|
+
require 'google_geocode'
|
5
|
+
|
6
|
+
class TestGoogleGeocode < Test::Unit::TestCase
|
7
|
+
|
8
|
+
def setup
|
9
|
+
URI::HTTP.responses = []
|
10
|
+
URI::HTTP.uris = []
|
11
|
+
|
12
|
+
@gg = GoogleGeocode.new 'APP_ID'
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_locate
|
16
|
+
URI::HTTP.responses << <<-EOF.strip
|
17
|
+
<?xml version="1.0" encoding="UTF-8"?><kml xmlns="http://earth.google.com/kml/2.0"><Response><name>1600 Amphitheatre Parkway, Mountain View, CA</name><Status><code>200</code><request>geocode</request></Status><Placemark><address>1600 Amphitheatre Pkwy, Mountain View, CA 94043, USA</address><AddressDetails xmlns="urn:oasis:names:tc:ciq:xsdschema:xAL:2.0"><Country><CountryNameCode>US</CountryNameCode><AdministrativeArea><AdministrativeAreaName>CA</AdministrativeAreaName><SubAdministrativeArea><SubAdministrativeAreaName>Santa Clara</SubAdministrativeAreaName><Locality><LocalityName>Mountain View</LocalityName><Thoroughfare><ThoroughfareName>1600 Amphitheatre Pkwy</ThoroughfareName></Thoroughfare><PostalCode><PostalCodeNumber>94043</PostalCodeNumber></PostalCode></Locality></SubAdministrativeArea></AdministrativeArea></Country></AddressDetails><Point><coordinates>-122.083739,37.423021,0</coordinates></Point></Placemark></Response></kml>
|
18
|
+
EOF
|
19
|
+
|
20
|
+
location = GoogleGeocode::Location.new
|
21
|
+
location.address = '1600 Amphitheatre Pkwy, Mountain View, CA 94043, USA'
|
22
|
+
location.latitude = 37.423021
|
23
|
+
location.longitude = -122.083739
|
24
|
+
|
25
|
+
assert_equal location,
|
26
|
+
@gg.locate('1600 Amphitheatre Parkway, Mountain View, CA')
|
27
|
+
|
28
|
+
assert_equal true, URI::HTTP.responses.empty?
|
29
|
+
assert_equal 1, URI::HTTP.uris.length
|
30
|
+
assert_equal 'http://maps.google.com/maps/geo?key=APP_ID&output=xml&q=1600%20Amphitheatre%20Parkway,%20Mountain%20View,%20CA',
|
31
|
+
URI::HTTP.uris.first
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_locate_bad_key
|
35
|
+
URI::HTTP.responses << <<-EOF.strip
|
36
|
+
<?xml version='1.0' encoding='UTF-8'?><kml xmlns='http://earth.google.com/kml/2.0'><Response><name>1600 Amphitheater Pkwy, Mountain View, CA</name><Status><code>610</code><request>geocode</request></Status></Response></kml>
|
37
|
+
EOF
|
38
|
+
|
39
|
+
@gg.locate 'x'
|
40
|
+
|
41
|
+
rescue GoogleGeocode::KeyError => e
|
42
|
+
assert_equal 'invalid key', e.message
|
43
|
+
else
|
44
|
+
flunk 'Error expected'
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_locate_bad_address
|
48
|
+
URI::HTTP.responses << <<-EOF.strip
|
49
|
+
<?xml version="1.0" encoding="UTF-8"?><kml xmlns="http://earth.google.com/kml/2.0"><Response><name>1600</name><Status><code>602</code><request>geocode</request></Status></Response></kml>
|
50
|
+
EOF
|
51
|
+
|
52
|
+
@gg.locate 'x'
|
53
|
+
|
54
|
+
rescue GoogleGeocode::AddressError => e
|
55
|
+
assert_equal 'invalid address', e.message
|
56
|
+
else
|
57
|
+
flunk 'Error expected'
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
class TestGoogleGeocodeLocation < Test::Unit::TestCase
|
63
|
+
|
64
|
+
def test_coordinates
|
65
|
+
location = GoogleGeocode::Location.new
|
66
|
+
location.address = '1600 Amphitheatre Pkwy, Mountain View, CA 94043, USA'
|
67
|
+
location.latitude = 37.423021
|
68
|
+
location.longitude = -122.083739
|
69
|
+
|
70
|
+
assert_equal [37.423021, -122.083739], location.coordinates
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
|
data/test/uri_stub.rb
ADDED
metadata
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
rubygems_version: 0.8.11.15
|
3
|
+
specification_version: 1
|
4
|
+
name: google-geocode
|
5
|
+
version: !ruby/object:Gem::Version
|
6
|
+
version: 1.0.0
|
7
|
+
date: 2006-06-12 00:00:00 -07:00
|
8
|
+
summary: Google Geocoder API Library
|
9
|
+
require_paths:
|
10
|
+
- lib
|
11
|
+
email: eric@robotcoop.com
|
12
|
+
homepage:
|
13
|
+
rubyforge_project:
|
14
|
+
description: Map addresses to latitude and longitude with Google's Geocoder.
|
15
|
+
autorequire:
|
16
|
+
default_executable:
|
17
|
+
bindir: bin
|
18
|
+
has_rdoc: true
|
19
|
+
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">"
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.0.0
|
24
|
+
version:
|
25
|
+
platform: ruby
|
26
|
+
signing_key:
|
27
|
+
cert_chain:
|
28
|
+
post_install_message:
|
29
|
+
authors:
|
30
|
+
- Eric Hodel
|
31
|
+
files:
|
32
|
+
- LICENSE
|
33
|
+
- Manifest.txt
|
34
|
+
- README
|
35
|
+
- Rakefile
|
36
|
+
- lib/google_geocode.rb
|
37
|
+
- test/test_google_geocode.rb
|
38
|
+
- test/uri_stub.rb
|
39
|
+
test_files: []
|
40
|
+
|
41
|
+
rdoc_options: []
|
42
|
+
|
43
|
+
extra_rdoc_files: []
|
44
|
+
|
45
|
+
executables: []
|
46
|
+
|
47
|
+
extensions: []
|
48
|
+
|
49
|
+
requirements: []
|
50
|
+
|
51
|
+
dependencies: []
|
52
|
+
|