geocoder 0.1.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of geocoder might be problematic. Click here for more details.

data/CHANGELOG ADDED
@@ -0,0 +1,4 @@
1
+ = 0.1.0
2
+ == February 8, 2006
3
+
4
+ * Initial release.
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2006 Paul Smith <paul@cnt.org>
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README ADDED
@@ -0,0 +1,122 @@
1
+ = Geocoder: Geocoding library for Ruby and command-line utility
2
+
3
+ Author:: Paul Smith <paul@cnt.org>
4
+ License:: MIT
5
+
6
+ Geocoder helps in converting street addresses to coordinate pairs,
7
+ specifically latitude and longitude (in degrees decimal). It also
8
+ provides address normalization.
9
+
10
+ It comes with a library so that Ruby developers can include geocoding
11
+ in their applications. It also comes with a command-line application,
12
+ <tt>geocode</tt>, that is useful for one-offs, shell scripts, and non-Ruby
13
+ applications.
14
+
15
+ == How it works
16
+
17
+ The Geocoder is basically a wrapper for geocoding web services.
18
+ Currently, two services are utilized: {Yahoo! Maps Geocoding
19
+ API}[http://developer.yahoo.net/maps/rest/V1/geocode.html], which
20
+ is an interface to their proprietary geocoding system; and
21
+ Geocoder.us[http://www.geocoder.us], which is basically a Perl
22
+ frontend to the TIGER/Line file from the US Census Bureau.
23
+
24
+ Unless the user or developer indicates otherwise, the Yahoo! Maps
25
+ API is used by default.
26
+
27
+ == Example: library
28
+
29
+ If you are going to use this library with the Yahoo! Maps Geocoding
30
+ service, you need to get yourself an {Application
31
+ ID}[http://developer.yahoo.net/faq/index.html#appid].
32
+
33
+ The very simplest use of the library would just instantiate a
34
+ Geocoder object and call the <tt>#geocode</tt> method, grab the
35
+ result, and get the values directly:
36
+
37
+ require 'geocoder'
38
+ geocoder = Geocoder::Yahoo.new "my_app_id" # => #<Geocoder::Yahoo:0x36b77c @appid="my_app_id">
39
+ result = geocoder.geocode "1600 pennsylvania ave nw washington dc"
40
+ result.lat # => "38.8987"
41
+ result.lng # => "-77.037223"
42
+ result.address # => "1600 PENNSYLVANIA AVE NW"
43
+ result.city # => "WASHINGTON"
44
+ result.state # => "DC"
45
+ result.zip # => "20502-0001"
46
+
47
+ The result that the <tt>geocode</tt> method returns is a subclass
48
+ of Array; each element contains the "closest match" for ambiguous
49
+ addresses, as determined by the remote geocoding service.
50
+
51
+ Any sort of production-level code would want to check for success
52
+ and watch for exceptions. Geocoding is an inexact science, so you
53
+ would want to check for success, and iterate over the refinements
54
+ or closest matches that the service returns:
55
+
56
+ require 'geocoder'
57
+ geocoder = Geocoder::Yahoo.new "my_app_id" # => #<Geocoder::Yahoo:0x36ae44 @appid="my_app_id">
58
+ result = geocoder.geocode "2038 damen ave chicago il"
59
+ result.success? # => false
60
+ result.each do |r|
61
+ r.lat # => "41.854524", "41.918759"
62
+ r.lng # => "-87.676083", "-87.67763"
63
+ r.address # => "2038 S DAMEN AVE", "2038 N DAMEN AVE"
64
+ r.city # => "CHICAGO", "CHICAGO"
65
+ r.state # => "IL", "IL"
66
+ r.zip # => "60608-2625", "60647-4564"
67
+ end
68
+
69
+ <tt>#success?</tt> is defined by a single result returned from the
70
+ geocoding service (and in the case of the Y! API, with no warning)
71
+
72
+ require 'geocoder'
73
+ geocoder = Geocoder::Yahoo.new "my_app_id"
74
+ begin
75
+ result = geocoder.geocode "thisisnotreal"
76
+ rescue Geocoder::GeocodingError
77
+ # do something appropriate to your application here
78
+ end
79
+
80
+ The Geocoder module defines 2 exception classes:
81
+
82
+ 1. BlankLocationString, thrown if a nil or a empty String is given to the geocode method;
83
+ 2. GeocodingError, thrown if the remote service indicates an error, for instance, on an ungeocodeable location
84
+
85
+ == Example: command-line utility
86
+
87
+ % geocode 2125 W North Ave, Chicago IL
88
+ Found 1 result(s).
89
+ ------------------
90
+ Latitude: 41.910263
91
+ Longitude: -87.680696
92
+ Address: 2125 W NORTH AVE
93
+ City: CHICAGO
94
+ State: IL
95
+ ZIP Code: 60647-5415
96
+
97
+ Notice that the geocoder normalizes the address, including city,
98
+ state, and ZIP Code.
99
+
100
+ You can also throw some switches on it. Try <tt>-q</tt> for quieter, CSV output:
101
+
102
+ % geocode -q 1600 pennsylvania ave nw washington dc
103
+ 38.8987,-77.037223,1600 PENNSYLVANIA AVE NW,WASHINGTON,DC,20502-0001
104
+
105
+ The order of the fields in the CSV output is:
106
+
107
+ 1. latitude (degrees decimal)
108
+ 2. longitude (degrees decimal)
109
+ 3. street address
110
+ 4. city
111
+ 5. state
112
+ 6. ZIP Code
113
+
114
+ == Usage: command-line utility
115
+
116
+ % geocode -h
117
+ Options:
118
+ -a, --appid appid Yahoo! Application ID
119
+ -s, --service service `yahoo' or `geocoderus'
120
+ -t, --timeout secs Timeout in seconds
121
+ -q, --quiet Quiet output
122
+ -h, --help Show this message
data/Rakefile ADDED
@@ -0,0 +1,42 @@
1
+ require 'rake/rdoctask'
2
+ require 'rake/gempackagetask'
3
+ require 'rubygems'
4
+
5
+ GEOCODER_VERSION = "0.1.0"
6
+
7
+ PKG_FILES = FileList["lib/**/*", "bin/**/*", "[A-Z]*",
8
+ "test/**/*"].exclude(/\b\.svn\b/)
9
+
10
+ desc "Run all tests"
11
+ task :default => [ :test ]
12
+
13
+ desc "Run all tests"
14
+ task :test do
15
+ ruby "test/ts_geocoder.rb"
16
+ end
17
+
18
+ desc "Generate documentation"
19
+ task :docs do
20
+ sh "rdoc -S -N -o doc -t \"Geocoder Documentation\" README TODO lib"
21
+ end
22
+
23
+ spec = Gem::Specification.new do |s|
24
+ s.platform = Gem::Platform::RUBY
25
+ s.summary = "Geocoding library and CLI."
26
+ s.name = "geocoder"
27
+ s.version = GEOCODER_VERSION
28
+ s.requirements << "none"
29
+ s.require_path = "lib"
30
+ s.author = "Paul Smith"
31
+ s.files = PKG_FILES
32
+ s.email = "paul@cnt.org"
33
+ s.rubyforge_project = "geocoder"
34
+ s.homepage = "http://geocoder.rubyforge.org"
35
+ s.bindir = "bin"
36
+ s.executables = ["geocode"]
37
+ end
38
+
39
+ Rake::GemPackageTask.new(spec) do |pkg|
40
+ pkg.need_zip = true
41
+ pkg.need_tar = true
42
+ end
data/TODO ADDED
@@ -0,0 +1,10 @@
1
+ = Geocoder To-Do list
2
+
3
+ Send suggestions to Paul Smith <paul@cnt.org>.
4
+
5
+ * unit tests for CLI
6
+ * many more tests of known and unknown addresses
7
+ * caching
8
+ * more services (c'mon, Google!)
9
+ * Rails plugin
10
+ * option to "average" results from more than one service
data/bin/geocode ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+ require 'geocoder'
3
+ cli = Geocoder::Cli.new ARGV
4
+ cli.go!
data/lib/geocoder.rb ADDED
@@ -0,0 +1,327 @@
1
+ #--
2
+ # Copyright (c) 2006 Paul Smith <paul@cnt.org>
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #++
23
+ #
24
+ # = Geocoder -- Geocoding library for Ruby
25
+ #
26
+ require 'cgi'
27
+ require 'net/http'
28
+ require 'rexml/document'
29
+ require 'timeout'
30
+
31
+ module Geocoder
32
+
33
+ class BlankLocationString < Exception; end
34
+ class GeocodingError < Exception; end
35
+
36
+ FIELDS = [ ["latitude", "Latitude"],
37
+ ["longitude", "Longitude"],
38
+ ["address", "Address"],
39
+ ["city", "City"],
40
+ ["state", "State"],
41
+ ["zip", "ZIP Code"] ].freeze
42
+
43
+ class Base
44
+ # +location+ is a string, any of the following:
45
+ # * city, state
46
+ # * city, state, zip
47
+ # * zip
48
+ # * street, city, state
49
+ # * street, city, state, zip
50
+ # * street, zip
51
+ def geocode location, *args
52
+ options = { :timeout => nil }
53
+ options.update(args.pop) if args.last.is_a?(Hash)
54
+ @options = options
55
+ if location.nil? or location.empty?
56
+ raise BlankLocationString
57
+ end
58
+ location = String location
59
+ results = parse request(location)
60
+ create_response results
61
+ end
62
+
63
+ def create_response results
64
+ Response.new results
65
+ end
66
+
67
+ # Makes an HTTP GET request on URL and returns the body
68
+ # of the response
69
+ def get url, timeout=5
70
+ url = URI.parse url
71
+ http = Net::HTTP.new url.host, url.port
72
+ res = Timeout::timeout(timeout) {
73
+ http.get url.request_uri
74
+ }
75
+ res.body
76
+ end
77
+
78
+ def request location
79
+ get url(location), @options[:timeout]
80
+ end
81
+ end
82
+
83
+ class GeoCoderUs < Base
84
+ def initialize *args
85
+ #
86
+ end
87
+
88
+ private
89
+
90
+ def parse csv_text
91
+ if csv_text =~ /^2: /
92
+ raise GeocodingError, csv_text.split(": ")[1]
93
+ end
94
+ results = []
95
+ csv_text.split("\n").each do |line|
96
+ latitude, longitude, address, city, state, zip = line.split ","
97
+ result = Result.new
98
+ result.latitude = latitude
99
+ result.longitude = longitude
100
+ result.address = address
101
+ result.city = city
102
+ result.state = state
103
+ result.zip = zip
104
+ results << result
105
+ end
106
+ results
107
+ end
108
+
109
+ # Returns URL of geocoder.us web service
110
+ def url address
111
+ "http://rpc.geocoder.us/service/csv?address=#{CGI.escape address}"
112
+ end
113
+ end
114
+
115
+ class Yahoo < Base
116
+ include REXML
117
+ # Requires a Y! Application ID
118
+ # http://developer.yahoo.net/faq/index.html#appid
119
+ def initialize appid
120
+ @appid = appid
121
+ end
122
+
123
+ private
124
+
125
+ # return array of results
126
+ def parse xml
127
+ # Create a new REXML::Document object from the raw XML text
128
+ xml = Document.new xml
129
+ #
130
+ # Normally, Y! will return an XML document with the root node
131
+ # <ResultSet>; if the request bombs, they return one with the
132
+ # root node <Error>
133
+ if is_error? xml
134
+ msgs = []
135
+ # Bubble up an exception using the error messages from Y!
136
+ xml.root.elements.each("Message") { |e| msgs << e.get_text.value }
137
+ raise GeocodingError, msgs.join(", ")
138
+ else
139
+ results = []
140
+ xml.root.elements.each "Result" do |e|
141
+ result = Result.new
142
+ # add fields
143
+ fields.each do |field|
144
+ text = e.elements[field.capitalize].get_text
145
+ if text.respond_to? :value
146
+ result.send "#{field}=", text.value
147
+ end
148
+ end
149
+ # add attributes
150
+ attributes.each do |attribute|
151
+ result.send "#{attribute}=", e.attributes[attribute]
152
+ end
153
+ results << result
154
+ end
155
+ results
156
+ end
157
+ end
158
+
159
+ def fields
160
+ %w| latitude longitude address city state zip country |
161
+ end
162
+
163
+ def attributes
164
+ %w| precision warning |
165
+ end
166
+
167
+ def is_error? document
168
+ document.root.name == "Error"
169
+ end
170
+
171
+ # Returns URL of Y! Geocoding web service
172
+ def url location
173
+ "http://api.local.yahoo.com/MapsService/V1/geocode?appid=#{@appid}&location=#{CGI.escape location}"
174
+ end
175
+ end
176
+
177
+ SERVICES = { :yahoo => Yahoo,
178
+ :geocoderus => GeoCoderUs }.freeze
179
+
180
+ class Result < Struct.new :latitude, :longitude, :address, :city,
181
+ :state, :zip, :country, :precision,
182
+ :warning
183
+ alias :lat :latitude
184
+ alias :lng :longitude
185
+ end
186
+
187
+ # A Response is a representation of the entire response from the
188
+ # Y! Geocoding web service, which may include multiple results,
189
+ # as well as warnings and errors
190
+ class Response < Array
191
+ def initialize results
192
+ results.each do |result|
193
+ self << result
194
+ end
195
+ end
196
+
197
+ # Geocoding was an unqualified success if one result in the result
198
+ # set is retured and there is no warning attribute in that result
199
+ def success?
200
+ size == 1 and self[0].warning.nil?
201
+ end
202
+
203
+ def bullseye?
204
+ success?
205
+ end
206
+
207
+ # Returns latitude in degrees decimal
208
+ def latitude
209
+ self[0].latitude if bullseye?
210
+ end
211
+
212
+ # Returns longitude in degrees decimal
213
+ def longitude
214
+ self[0].longitude if bullseye?
215
+ end
216
+
217
+ # Returns normalized street address, capitalized
218
+ def address
219
+ self[0].address if bullseye?
220
+ end
221
+
222
+ # Returns normalized city name, capitalized
223
+ def city
224
+ self[0].city if bullseye?
225
+ end
226
+
227
+ # Returns normalized two-letter USPS state abbreviation
228
+ def state
229
+ self[0].state if bullseye?
230
+ end
231
+
232
+ alias_method :array_zip, :zip
233
+
234
+ # Returns normalized ZIP Code, or postal code
235
+ def zip
236
+ self[0].zip if bullseye?
237
+ end
238
+
239
+ # Returns two-letter country code abbreviation
240
+ def country
241
+ self[0].country if bullseye?
242
+ end
243
+
244
+ alias :lat :latitude
245
+ alias :lng :longitude
246
+ end
247
+
248
+ class Cli
249
+ require 'optparse'
250
+ require 'ostruct'
251
+
252
+ def self.parse args
253
+ options = OpenStruct.new
254
+ # default values
255
+ options.appid = "YahooDemo"
256
+ options.service = Yahoo
257
+ options.timeout = 5
258
+ opts = OptionParser.new do |opts|
259
+ opts.banner = "Usage: geocode [options] location"
260
+ opts.separator ""
261
+ opts.separator "Options:"
262
+ opts.on "-a appid", "--appid appid", "Yahoo! Application ID" do |a|
263
+ options.appid = a
264
+ end
265
+ opts.on "-s service", "--service service", "`yahoo' or `geocoderus'" do |s|
266
+ options.service = SERVICES[s]
267
+ end
268
+ opts.on "-t secs", "--timeout secs", Integer, "Timeout in seconds" do |t|
269
+ options.timeout = t
270
+ end
271
+ opts.on "-q", "--quiet", "Quiet output" do |q|
272
+ options.quiet = q
273
+ end
274
+ opts.on_tail "-h", "--help", "Show this message" do
275
+ puts opts
276
+ exit
277
+ end
278
+ opts.parse! args
279
+ end
280
+ [options, opts]
281
+ end
282
+
283
+ def initialize cli_args
284
+ @options, @opt_parser = Cli::parse cli_args
285
+ @location = cli_args.join " "
286
+ end
287
+
288
+ def report result
289
+ buffer = []
290
+ if @options.quiet
291
+ result.each do |r|
292
+ buffer << FIELDS.collect do |k,v|
293
+ r.send k
294
+ end.join(",")
295
+ end
296
+ else
297
+ buffer << "Found #{result.size} result(s)."
298
+ buffer << buffer.last.gsub(/./, "-")
299
+ buffer << result.collect do |r|
300
+ FIELDS.collect do |k,v|
301
+ "#{v}: #{r.send k}"
302
+ end.join("\n")
303
+ end.join("\n- - - -\n")
304
+ end
305
+ puts buffer.join("\n")
306
+ end
307
+
308
+ def go!
309
+ g = @options.service.new @options.appid
310
+ begin
311
+ result = g.geocode @location, :timeout => @options.timeout
312
+ report result
313
+ rescue BlankLocationString
314
+ STDERR.puts "You have to give an address to geocode!"
315
+ puts
316
+ puts @opt_parser
317
+ exit
318
+ rescue Timeout::Error
319
+ STDERR.puts "The remote geocoding service timed-out. Try increasing the timeout value (-t)."
320
+ exit
321
+ rescue Geocoder::GeocodingError => e
322
+ STDERR.puts "Geocoder: #{e}"
323
+ exit
324
+ end
325
+ end
326
+ end
327
+ end
@@ -0,0 +1,2 @@
1
+ 41.854436,-87.675853,2038 S Damen Ave,Chicago,IL,60608
2
+ 41.918850,-87.677800,2038 N Damen Ave,Chicago,IL,60647
@@ -0,0 +1 @@
1
+ 41.910408,-87.680592,2125 W North Ave,Chicago,IL,60647
@@ -0,0 +1 @@
1
+ 2: couldn't find this address! sorry
@@ -0,0 +1,4 @@
1
+ <?xml version="1.0" encoding="UTF-8"?> <Error xmlns="urn:yahoo:api">
2
+ The following errors were detected:
3
+ <Message>unable to parse location</Message></Error>
4
+ <!-- ws02.search.scd.yahoo.com uncompressed/chunked Fri Feb 3 16:08:33 PST 2006 -->
@@ -0,0 +1,2 @@
1
+ <?xml version="1.0" encoding="UTF-8"?><ResultSet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:yahoo:maps" xsi:schemaLocation="urn:yahoo:maps http://api.local.yahoo.com/MapsService/V1/GeocodeResponse.xsd"><Result precision="address" warning="The exact location could not be found, here is the closest match: 2038 S Damen Ave, Chicago, IL 60608"><Latitude>41.854524</Latitude><Longitude>-87.676083</Longitude><Address>2038 S DAMEN AVE</Address><City>CHICAGO</City><State>IL</State><Zip>60608-2625</Zip><Country>US</Country></Result><Result precision="address" warning="The exact location could not be found, here is the closest match: 2038 N Damen Ave, Chicago, IL 60647"><Latitude>41.918759</Latitude><Longitude>-87.67763</Longitude><Address>2038 N DAMEN AVE</Address><City>CHICAGO</City><State>IL</State><Zip>60647-4564</Zip><Country>US</Country></Result></ResultSet>
2
+ <!-- ws01.search.scd.yahoo.com uncompressed Fri Feb 3 14:49:21 PST 2006 -->
@@ -0,0 +1,2 @@
1
+ <?xml version="1.0" encoding="UTF-8"?><ResultSet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:yahoo:maps" xsi:schemaLocation="urn:yahoo:maps http://api.local.yahoo.com/MapsService/V1/GeocodeResponse.xsd"><Result precision="address"><Latitude>41.910263</Latitude><Longitude>-87.680696</Longitude><Address>2125 W NORTH AVE</Address><City>CHICAGO</City><State>IL</State><Zip>60647-5415</Zip><Country>US</Country></Result></ResultSet>
2
+ <!-- ws01.search.scd.yahoo.com uncompressed Fri Feb 3 14:49:43 PST 2006 -->
@@ -0,0 +1,4 @@
1
+ <?xml version="1.0" encoding="UTF-8"?> <Error xmlns="urn:yahoo:api">
2
+ The following errors were detected:
3
+ <Message>unable to parse location</Message></Error>
4
+ <!-- ws02.search.scd.yahoo.com uncompressed/chunked Tue Feb 7 14:52:36 PST 2006 -->
@@ -0,0 +1,19 @@
1
+ require 'net/http'
2
+
3
+ module Net
4
+ class HTTP
5
+ alias_method :old_get, :get
6
+ def get(path, *args)
7
+ begin
8
+ filename = File.dirname(__FILE__) + "/" + File.basename(path)
9
+ return File.open(filename)
10
+ rescue Errno::ENOENT
11
+ old_get(path, *args)
12
+ end
13
+ end
14
+ end
15
+ end
16
+
17
+ class File
18
+ alias_method :body, :read
19
+ end
data/test/sample.xml ADDED
@@ -0,0 +1,2 @@
1
+ <?xml version="1.0" encoding="UTF-8"?><ResultSet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:yahoo:maps" xsi:schemaLocation="urn:yahoo:maps http://api.local.yahoo.com/MapsService/V1/GeocodeResponse.xsd"><Result precision="address"><Latitude>41.910263</Latitude><Longitude>-87.680696</Longitude><Address>2125 W NORTH AVE</Address><City>CHICAGO</City><State>IL</State><Zip>60647-5415</Zip><Country>US</Country></Result></ResultSet>
2
+ <!-- ws02.search.re2.yahoo.com uncompressed Wed Jan 25 14:06:31 PST 2006 -->
@@ -0,0 +1,105 @@
1
+ require 'test/unit'
2
+ require File.dirname(__FILE__) + '/../lib/geocoder'
3
+ require File.dirname(__FILE__) + '/mocks/http'
4
+
5
+ class TC_GeoCoderUsSuccess < Test::Unit::TestCase
6
+ include Geocoder
7
+
8
+ def setup
9
+ @geocoder = GeoCoderUs.new
10
+ @response = @geocoder.geocode "2125 w north ave chicago il"
11
+ end
12
+
13
+ def test_success
14
+ assert_equal true, @response.success?
15
+ end
16
+
17
+ def test_latitude
18
+ assert_in_delta 41.910408, @response.latitude, 0.0005
19
+ end
20
+
21
+ def test_longitude
22
+ assert_in_delta -87.680592, @response.longitude, 0.0005
23
+ end
24
+
25
+ def test_address
26
+ assert_equal "2125 W North Ave", @response.address
27
+ end
28
+
29
+ def test_city
30
+ assert_equal "Chicago", @response.city
31
+ end
32
+
33
+ def test_state
34
+ assert_equal "IL", @response.state
35
+ end
36
+
37
+ def test_zip
38
+ assert_equal "60647", @response.zip
39
+ end
40
+
41
+ def test_lat
42
+ assert_respond_to @response, :lat
43
+ assert_same @response.lat, @response.latitude
44
+ end
45
+
46
+ def test_lng
47
+ assert_respond_to @response, :lng
48
+ assert_same @response.lng, @response.lng
49
+ end
50
+ end
51
+
52
+ class TC_GeoCoderUsAmbiguous < Test::Unit::TestCase
53
+ include Geocoder
54
+
55
+ def setup
56
+ @geocoder = GeoCoderUs.new
57
+ @response = @geocoder.geocode "2038 damen ave chicago il"
58
+ end
59
+
60
+ def test_success
61
+ assert_equal false, @response.success?
62
+ end
63
+
64
+ def test_matches
65
+ assert_equal 2, @response.size
66
+ end
67
+
68
+ def test_warning
69
+ @response.each do |result|
70
+ assert_nil result.warning
71
+ end
72
+ end
73
+
74
+ def test_precision
75
+ @response.each do |result|
76
+ assert_nil result.precision
77
+ end
78
+ end
79
+ end
80
+
81
+ class TC_GeoCoderUsExceptions < Test::Unit::TestCase
82
+ include Geocoder
83
+
84
+ def setup
85
+ @geocoder = GeoCoderUs.new
86
+ end
87
+
88
+ def test_throws_on_nil
89
+ assert_raise(Geocoder::BlankLocationString) {
90
+ @geocoder.geocode nil
91
+ }
92
+ end
93
+
94
+ def test_throws_on_empty_string
95
+ assert_raise(Geocoder::BlankLocationString) {
96
+ @geocoder.geocode ""
97
+ }
98
+ end
99
+
100
+ def test_throws_on_ungeocodeable
101
+ assert_raise(Geocoder::GeocodingError) {
102
+ @geocoder.geocode "donotleaveitisnotreal"
103
+ }
104
+ end
105
+ end
data/test/tc_yahoo.rb ADDED
@@ -0,0 +1,110 @@
1
+ require 'test/unit'
2
+ require File.dirname(__FILE__) + '/../lib/geocoder'
3
+ require File.dirname(__FILE__) + '/mocks/http'
4
+
5
+ class TC_YahooGeocoderSuccess < Test::Unit::TestCase
6
+ include Geocoder
7
+
8
+ def setup
9
+ @geocoder = Yahoo.new "YahooDemo"
10
+ @response = @geocoder.geocode "2125 w north ave chicago il"
11
+ end
12
+
13
+ def test_success
14
+ assert_equal true, @response.success?
15
+ end
16
+
17
+ def test_latitude
18
+ assert_in_delta 41.910263, @response.latitude, 0.0005
19
+ end
20
+
21
+ def test_longitude
22
+ assert_in_delta -87.680696, @response.longitude, 0.0005
23
+ end
24
+
25
+ def test_address
26
+ assert_equal "2125 W NORTH AVE", @response.address
27
+ end
28
+
29
+ def test_city
30
+ assert_equal "CHICAGO", @response.city
31
+ end
32
+
33
+ def test_state
34
+ assert_equal "IL", @response.state
35
+ end
36
+
37
+ def test_zip
38
+ assert_equal "60647-5415", @response.zip
39
+ end
40
+
41
+ def test_country
42
+ assert_equal "US", @response.country
43
+ end
44
+
45
+ def test_lat
46
+ assert_respond_to @response, :lat
47
+ assert_same @response.lat, @response.latitude
48
+ end
49
+
50
+ def test_lng
51
+ assert_respond_to @response, :lng
52
+ assert_same @response.lng, @response.lng
53
+ end
54
+ end
55
+
56
+ class TC_YahooGeocoderAmbiguous < Test::Unit::TestCase
57
+ include Geocoder
58
+
59
+ def setup
60
+ @geocoder = Yahoo.new "YahooDemo"
61
+ @response = @geocoder.geocode "2038 damen ave chicago il"
62
+ end
63
+
64
+ def test_success
65
+ assert_equal false, @response.success?
66
+ end
67
+
68
+ def test_matches
69
+ assert_equal 2, @response.size
70
+ end
71
+
72
+ def test_warning
73
+ @response.each do |result|
74
+ assert_match %r{^The exact location could not be found, here is the closest match:},
75
+ result.warning
76
+ end
77
+ end
78
+
79
+ def test_precision
80
+ @response.each do |result|
81
+ assert_equal "address", result.precision
82
+ end
83
+ end
84
+ end
85
+
86
+ class TC_YahooGeocoderExceptions < Test::Unit::TestCase
87
+ include Geocoder
88
+
89
+ def setup
90
+ @geocoder = Yahoo.new "YahooDemo"
91
+ end
92
+
93
+ def test_throws_on_nil
94
+ assert_raise(Geocoder::BlankLocationString) {
95
+ @geocoder.geocode nil
96
+ }
97
+ end
98
+
99
+ def test_throws_on_empty_string
100
+ assert_raise(Geocoder::BlankLocationString) {
101
+ @geocoder.geocode ""
102
+ }
103
+ end
104
+
105
+ def test_throws_on_ungeocodeable
106
+ assert_raise(Geocoder::GeocodingError) {
107
+ @geocoder.geocode "donotleaveitisnotreal"
108
+ }
109
+ end
110
+ end
@@ -0,0 +1,4 @@
1
+ require 'test/unit'
2
+ %w{ tc_yahoo tc_geocoderus }.each { |tc|
3
+ require File.dirname(__FILE__) + "/#{tc}"
4
+ }
metadata ADDED
@@ -0,0 +1,64 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.8.11
3
+ specification_version: 1
4
+ name: geocoder
5
+ version: !ruby/object:Gem::Version
6
+ version: 0.1.0
7
+ date: 2006-02-08 00:00:00 -06:00
8
+ summary: Geocoding library and CLI.
9
+ require_paths:
10
+ - lib
11
+ email: paul@cnt.org
12
+ homepage: http://geocoder.rubyforge.org
13
+ rubyforge_project: geocoder
14
+ description:
15
+ autorequire:
16
+ default_executable:
17
+ bindir: bin
18
+ has_rdoc: false
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
+ authors:
29
+ - Paul Smith
30
+ files:
31
+ - lib/geocoder.rb
32
+ - bin/geocode
33
+ - CHANGELOG
34
+ - LICENSE
35
+ - Rakefile
36
+ - README
37
+ - TODO
38
+ - test/mocks
39
+ - test/sample.xml
40
+ - test/tc_geocoderus.rb
41
+ - test/tc_yahoo.rb
42
+ - test/ts_geocoder.rb
43
+ - test/mocks/csv?address=2038+damen+ave+chicago+il
44
+ - test/mocks/csv?address=2125+w+north+ave+chicago+il
45
+ - test/mocks/csv?address=donotleaveitisnotreal
46
+ - test/mocks/geocode?appid=YahooDemo&location=
47
+ - test/mocks/geocode?appid=YahooDemo&location=2038+damen+ave+chicago+il
48
+ - test/mocks/geocode?appid=YahooDemo&location=2125+w+north+ave+chicago+il
49
+ - test/mocks/geocode?appid=YahooDemo&location=donotleaveitisnotreal
50
+ - test/mocks/http.rb
51
+ test_files: []
52
+
53
+ rdoc_options: []
54
+
55
+ extra_rdoc_files: []
56
+
57
+ executables:
58
+ - geocode
59
+ extensions: []
60
+
61
+ requirements:
62
+ - none
63
+ dependencies: []
64
+