geocoder 0.1.1 → 0.9.8
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.rdoc +96 -0
- data/LICENSE +1 -1
- data/README.rdoc +215 -0
- data/Rakefile +46 -43
- data/lib/geocoder.rb +17 -321
- data/lib/geocoder/active_record.rb +235 -0
- data/lib/geocoder/calculations.rb +94 -0
- data/lib/geocoder/configuration.rb +8 -0
- data/lib/geocoder/lookup.rb +90 -0
- data/lib/geocoder/railtie.rb +68 -0
- data/lib/geocoder/result.rb +42 -0
- data/lib/tasks/geocoder.rake +15 -0
- data/test/geocoder_test.rb +36 -0
- data/test/test_helper.rb +97 -0
- metadata +68 -51
- data/CHANGELOG +0 -10
- data/README +0 -122
- data/TODO +0 -10
- data/bin/geocode +0 -4
- data/test/mocks/csv?address=2038+damen+ave+chicago+il +0 -2
- data/test/mocks/csv?address=2125+w+north+ave+chicago+il +0 -1
- data/test/mocks/csv?address=donotleaveitisnotreal +0 -1
- data/test/mocks/geocode?appid=YahooDemo&location= +0 -4
- data/test/mocks/geocode?appid=YahooDemo&location=2038+damen+ave+chicago+il +0 -2
- data/test/mocks/geocode?appid=YahooDemo&location=2125+w+north+ave+chicago+il +0 -2
- data/test/mocks/geocode?appid=YahooDemo&location=donotleaveitisnotreal +0 -4
- data/test/mocks/http.rb +0 -19
- data/test/sample.xml +0 -2
- data/test/tc_geocoderus.rb +0 -105
- data/test/tc_yahoo.rb +0 -110
- data/test/ts_geocoder.rb +0 -4
@@ -0,0 +1,42 @@
|
|
1
|
+
module Geocoder
|
2
|
+
class Result
|
3
|
+
attr_accessor :data
|
4
|
+
|
5
|
+
##
|
6
|
+
# Takes a hash of result data from a parsed Google result document.
|
7
|
+
#
|
8
|
+
def initialize(data)
|
9
|
+
@data = data
|
10
|
+
end
|
11
|
+
|
12
|
+
def types
|
13
|
+
@data['types']
|
14
|
+
end
|
15
|
+
|
16
|
+
def formatted_address
|
17
|
+
@data['formatted_address']
|
18
|
+
end
|
19
|
+
|
20
|
+
def address_components
|
21
|
+
@data['address_components']
|
22
|
+
end
|
23
|
+
|
24
|
+
##
|
25
|
+
# Get address components of a given type. Valid types are defined in
|
26
|
+
# Google's Geocoding API documentation and include (among others):
|
27
|
+
#
|
28
|
+
# :street_number
|
29
|
+
# :locality
|
30
|
+
# :neighborhood
|
31
|
+
# :route
|
32
|
+
# :postal_code
|
33
|
+
#
|
34
|
+
def address_components_of_type(type)
|
35
|
+
address_components.select{ |c| c['types'].include?(type.to_s) }
|
36
|
+
end
|
37
|
+
|
38
|
+
def geometry
|
39
|
+
@data['geometry']
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
def klass
|
2
|
+
class_name = ENV['CLASS'] || ENV['class']
|
3
|
+
raise "Please specify a CLASS (model)" unless class_name
|
4
|
+
Object.const_get(class_name)
|
5
|
+
end
|
6
|
+
|
7
|
+
namespace :geocode do
|
8
|
+
|
9
|
+
desc "Geocode all objects without coordinates."
|
10
|
+
task :all => :environment do
|
11
|
+
klass.not_geocoded.each do |obj|
|
12
|
+
obj.fetch_coordinates!
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class GeocoderTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
def test_fetch_coordinates
|
6
|
+
v = Venue.new(*venue_params(:msg))
|
7
|
+
assert_equal [40.750354, -73.993371], v.fetch_coordinates
|
8
|
+
assert_equal [40.750354, -73.993371], [v.latitude, v.longitude]
|
9
|
+
end
|
10
|
+
|
11
|
+
# sanity check
|
12
|
+
def test_distance_between
|
13
|
+
assert_equal 69, Geocoder::Calculations.distance_between(0,0, 0,1).round
|
14
|
+
end
|
15
|
+
|
16
|
+
# sanity check
|
17
|
+
def test_geographic_center
|
18
|
+
assert_equal [0.0, 0.5],
|
19
|
+
Geocoder::Calculations.geographic_center([[0,0], [0,1]])
|
20
|
+
assert_equal [0.0, 1.0],
|
21
|
+
Geocoder::Calculations.geographic_center([[0,0], [0,1], [0,2]])
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_exception_raised_for_unconfigured_geocoding
|
25
|
+
l = Landmark.new("Mount Rushmore", 43.88, -103.46)
|
26
|
+
assert_raises Geocoder::ConfigurationError do
|
27
|
+
l.fetch_coordinates
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_result_address_components_of_type
|
32
|
+
results = Geocoder::Lookup.search("Madison Square Garden, New York, NY")
|
33
|
+
assert_equal "Manhattan",
|
34
|
+
results.first.address_components_of_type(:sublocality).first['long_name']
|
35
|
+
end
|
36
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'test/unit'
|
3
|
+
require 'active_support/core_ext'
|
4
|
+
|
5
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
6
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
7
|
+
|
8
|
+
##
|
9
|
+
# Simulate enough of ActiveRecord::Base that objects can be used for testing.
|
10
|
+
#
|
11
|
+
module ActiveRecord
|
12
|
+
class Base
|
13
|
+
|
14
|
+
def initialize
|
15
|
+
@attributes = {}
|
16
|
+
end
|
17
|
+
|
18
|
+
def read_attribute(attr_name)
|
19
|
+
@attributes[attr_name.to_sym]
|
20
|
+
end
|
21
|
+
|
22
|
+
def write_attribute(attr_name, value)
|
23
|
+
@attributes[attr_name.to_sym] = value
|
24
|
+
end
|
25
|
+
|
26
|
+
def update_attribute(attr_name, value)
|
27
|
+
write_attribute(attr_name.to_sym, value)
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.scope(*args); end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# Require Geocoder after ActiveRecord simulator.
|
35
|
+
require 'geocoder'
|
36
|
+
|
37
|
+
##
|
38
|
+
# Mock HTTP request to geocoding service.
|
39
|
+
#
|
40
|
+
module Geocoder
|
41
|
+
module Lookup
|
42
|
+
extend self
|
43
|
+
private #-----------------------------------------------------------------
|
44
|
+
def fetch_data(query, reverse = false)
|
45
|
+
File.read(File.join("test", "fixtures", "madison_square_garden.json"))
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
##
|
51
|
+
# Geocoded model.
|
52
|
+
#
|
53
|
+
class Venue < ActiveRecord::Base
|
54
|
+
geocoded_by :address
|
55
|
+
|
56
|
+
def initialize(name, address)
|
57
|
+
super()
|
58
|
+
write_attribute :name, name
|
59
|
+
write_attribute :address, address
|
60
|
+
end
|
61
|
+
|
62
|
+
##
|
63
|
+
# If method not found, assume it's an ActiveRecord attribute reader.
|
64
|
+
#
|
65
|
+
def method_missing(name, *args, &block)
|
66
|
+
@attributes[name]
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
##
|
71
|
+
# Reverse geocoded model.
|
72
|
+
#
|
73
|
+
class Landmark < ActiveRecord::Base
|
74
|
+
reverse_geocoded_by :latitude, :longitude
|
75
|
+
|
76
|
+
def initialize(name, latitude, longitude)
|
77
|
+
super()
|
78
|
+
write_attribute :name, name
|
79
|
+
write_attribute :latitude, latitude
|
80
|
+
write_attribute :longitude, longitude
|
81
|
+
end
|
82
|
+
|
83
|
+
##
|
84
|
+
# If method not found, assume it's an ActiveRecord attribute reader.
|
85
|
+
#
|
86
|
+
def method_missing(name, *args, &block)
|
87
|
+
@attributes[name]
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
class Test::Unit::TestCase
|
92
|
+
def venue_params(abbrev)
|
93
|
+
{
|
94
|
+
:msg => ["Madison Square Garden", "4 Penn Plaza, New York, NY"]
|
95
|
+
}[abbrev]
|
96
|
+
end
|
97
|
+
end
|
metadata
CHANGED
@@ -1,64 +1,81 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
|
-
rubygems_version: 0.8.11
|
3
|
-
specification_version: 1
|
4
2
|
name: geocoder
|
5
3
|
version: !ruby/object:Gem::Version
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
-
|
11
|
-
|
12
|
-
|
13
|
-
rubyforge_project: geocoder
|
14
|
-
description:
|
15
|
-
autorequire: geocoder
|
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:
|
4
|
+
hash: 43
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 9
|
9
|
+
- 8
|
10
|
+
version: 0.9.8
|
25
11
|
platform: ruby
|
26
|
-
signing_key:
|
27
|
-
cert_chain:
|
28
12
|
authors:
|
29
|
-
-
|
13
|
+
- Alex Reisner
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-02-14 00:00:00 -05:00
|
19
|
+
default_executable:
|
20
|
+
dependencies: []
|
21
|
+
|
22
|
+
description: Geocoder adds object geocoding and distance calculations to ActiveRecord models. It does not rely on proprietary database functions so finding geocoded objects in a given area is easily done using out-of-the-box MySQL, PostgreSQL, or SQLite.
|
23
|
+
email:
|
24
|
+
- alex@alexreisner.com
|
25
|
+
executables: []
|
26
|
+
|
27
|
+
extensions: []
|
28
|
+
|
29
|
+
extra_rdoc_files: []
|
30
|
+
|
30
31
|
files:
|
31
32
|
- lib/geocoder.rb
|
32
|
-
-
|
33
|
-
-
|
34
|
-
-
|
33
|
+
- lib/geocoder/lookup.rb
|
34
|
+
- lib/geocoder/calculations.rb
|
35
|
+
- lib/geocoder/railtie.rb
|
36
|
+
- lib/geocoder/result.rb
|
37
|
+
- lib/geocoder/configuration.rb
|
38
|
+
- lib/geocoder/active_record.rb
|
39
|
+
- lib/tasks/geocoder.rake
|
40
|
+
- test/test_helper.rb
|
41
|
+
- test/geocoder_test.rb
|
42
|
+
- CHANGELOG.rdoc
|
35
43
|
- Rakefile
|
36
|
-
- README
|
37
|
-
-
|
38
|
-
|
39
|
-
|
40
|
-
|
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: []
|
44
|
+
- README.rdoc
|
45
|
+
- LICENSE
|
46
|
+
has_rdoc: true
|
47
|
+
homepage: http://github.com/alexreisner/geocoder
|
48
|
+
licenses: []
|
52
49
|
|
50
|
+
post_install_message:
|
53
51
|
rdoc_options: []
|
54
52
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
53
|
+
require_paths:
|
54
|
+
- lib
|
55
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
56
|
+
none: false
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
hash: 3
|
61
|
+
segments:
|
62
|
+
- 0
|
63
|
+
version: "0"
|
64
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
hash: 3
|
70
|
+
segments:
|
71
|
+
- 0
|
72
|
+
version: "0"
|
73
|
+
requirements: []
|
60
74
|
|
61
|
-
|
62
|
-
|
63
|
-
|
75
|
+
rubyforge_project:
|
76
|
+
rubygems_version: 1.3.7
|
77
|
+
signing_key:
|
78
|
+
specification_version: 3
|
79
|
+
summary: Simple, database-agnostic geocoding and distance calculations for Rails.
|
80
|
+
test_files: []
|
64
81
|
|
data/CHANGELOG
DELETED
data/README
DELETED
@@ -1,122 +0,0 @@
|
|
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
|