hacked0ff-reverse_geocode 0.0.1
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 +20 -0
- data/README +3 -0
- data/Rakefile +57 -0
- data/TODO +4 -0
- data/lib/reverse_geocode.rb +92 -0
- data/spec/reverse_geocode_spec.rb +164 -0
- data/spec/spec_helper.rb +6 -0
- metadata +70 -0
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 YOUR NAME
|
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
data/Rakefile
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake/gempackagetask'
|
3
|
+
require 'rubygems/specification'
|
4
|
+
require 'date'
|
5
|
+
require 'spec/rake/spectask'
|
6
|
+
|
7
|
+
GEM = "reverse_geocode"
|
8
|
+
GEM_VERSION = "0.0.1"
|
9
|
+
AUTHOR = "Your Name"
|
10
|
+
EMAIL = "Your Email"
|
11
|
+
HOMEPAGE = "http://example.com"
|
12
|
+
SUMMARY = "A gem that provides..."
|
13
|
+
|
14
|
+
spec = Gem::Specification.new do |s|
|
15
|
+
s.name = GEM
|
16
|
+
s.version = GEM_VERSION
|
17
|
+
s.platform = Gem::Platform::RUBY
|
18
|
+
s.has_rdoc = true
|
19
|
+
s.extra_rdoc_files = ["README", "LICENSE", 'TODO']
|
20
|
+
s.summary = SUMMARY
|
21
|
+
s.description = s.summary
|
22
|
+
s.author = AUTHOR
|
23
|
+
s.email = EMAIL
|
24
|
+
s.homepage = HOMEPAGE
|
25
|
+
|
26
|
+
# Uncomment this to add a dependency
|
27
|
+
# s.add_dependency "foo"
|
28
|
+
|
29
|
+
s.require_path = 'lib'
|
30
|
+
s.autorequire = GEM
|
31
|
+
s.files = %w(LICENSE README Rakefile TODO) + Dir.glob("{lib,spec}/**/*")
|
32
|
+
end
|
33
|
+
|
34
|
+
task :default => :spec
|
35
|
+
|
36
|
+
desc "Run specs"
|
37
|
+
Spec::Rake::SpecTask.new do |t|
|
38
|
+
t.spec_files = FileList['spec/**/*_spec.rb']
|
39
|
+
t.spec_opts = %w(-fs --color)
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
Rake::GemPackageTask.new(spec) do |pkg|
|
44
|
+
pkg.gem_spec = spec
|
45
|
+
end
|
46
|
+
|
47
|
+
desc "install the gem locally"
|
48
|
+
task :install => [:package] do
|
49
|
+
sh %{sudo gem install pkg/#{GEM}-#{GEM_VERSION}}
|
50
|
+
end
|
51
|
+
|
52
|
+
desc "create a gemspec file"
|
53
|
+
task :make_spec do
|
54
|
+
File.open("#{GEM}.gemspec", "w") do |file|
|
55
|
+
file.puts spec.to_ruby
|
56
|
+
end
|
57
|
+
end
|
data/TODO
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'uri'
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
class ReverseGeocode
|
6
|
+
class GeocodeError < StandardError
|
7
|
+
ERRORS = {
|
8
|
+
400 => "Bad Request",
|
9
|
+
500 => "Server Error",
|
10
|
+
601 => "Missing Query or Address",
|
11
|
+
602 => "Unknown Address",
|
12
|
+
603 => "Unavailable Address",
|
13
|
+
604 => "Unknown Directions",
|
14
|
+
610 => "Bad Key",
|
15
|
+
620 => "Too Many Queries"
|
16
|
+
}
|
17
|
+
|
18
|
+
def initialize(error_code)
|
19
|
+
super("#{error_code}: #{ERRORS[error_code]}")
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class << self; attr_accessor :api_key; end
|
24
|
+
|
25
|
+
attr_reader :lat, :long
|
26
|
+
def initialize(lat, long)
|
27
|
+
raise ArgumentError, "Latitude and longitude required" unless lat && long
|
28
|
+
@lat, @long = lat, long
|
29
|
+
end
|
30
|
+
|
31
|
+
def response
|
32
|
+
@response ||= handle_response
|
33
|
+
end
|
34
|
+
|
35
|
+
def address
|
36
|
+
@address ||= first_placemark/'address'
|
37
|
+
end
|
38
|
+
|
39
|
+
def street
|
40
|
+
@street ||= first_administrative_area/'Thoroughfare'/'ThoroughfareName'
|
41
|
+
end
|
42
|
+
|
43
|
+
def state
|
44
|
+
@state ||= first_administrative_area/'AdministrativeAreaName'
|
45
|
+
end
|
46
|
+
|
47
|
+
def zip
|
48
|
+
@zip ||= first_administrative_area/'PostalCode'/'PostalCodeNumber'
|
49
|
+
end
|
50
|
+
|
51
|
+
def city
|
52
|
+
@city ||= placemark[1]/'AddressDetails'/'Country'/'AdministrativeArea'/'Locality'/'LocalityName'
|
53
|
+
end
|
54
|
+
|
55
|
+
def county
|
56
|
+
@county ||= (placemark[3]/'AddressDetails'/'Country'/'AdministrativeArea'/'AddressLine').first
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
def first_placemark
|
62
|
+
placemark[0]
|
63
|
+
end
|
64
|
+
|
65
|
+
def first_administrative_area
|
66
|
+
first_placemark/'AddressDetails'/'Country'/'AdministrativeArea'
|
67
|
+
end
|
68
|
+
|
69
|
+
def placemark
|
70
|
+
(response/"Placemark")
|
71
|
+
end
|
72
|
+
|
73
|
+
def reverse_geocode_uri
|
74
|
+
URI.parse("http://maps.google.com/maps/geo?ll=#{URI.escape(lat.to_s)},#{URI.escape(long.to_s)}&output=json")
|
75
|
+
end
|
76
|
+
|
77
|
+
def parse_json
|
78
|
+
body = Net::HTTP.get_response(reverse_geocode_uri).body
|
79
|
+
JSON.parse(body)
|
80
|
+
end
|
81
|
+
|
82
|
+
def handle_response
|
83
|
+
hash = parse_json
|
84
|
+
status_code = (hash/'Status'/'code').to_i
|
85
|
+
raise GeocodeError, status_code if status_code >= 400
|
86
|
+
return hash
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
class Hash
|
91
|
+
alias_method :/, :[]
|
92
|
+
end
|
@@ -0,0 +1,164 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
describe "ReverseGeocode" do
|
4
|
+
before do
|
5
|
+
@attrs = {
|
6
|
+
:lat => 30.009897,
|
7
|
+
:long => -81.387655,
|
8
|
+
:address => "439-499 La Travesia Flora, FL 32095, USA",
|
9
|
+
:street => "439-499 La Travesia Flora",
|
10
|
+
:state => "FL",
|
11
|
+
:city => "St Augustine",
|
12
|
+
:zip => "32095",
|
13
|
+
:county => "St Johns"
|
14
|
+
}
|
15
|
+
|
16
|
+
@response = {"Status"=>{"code"=>200, "request"=>"geocode"},
|
17
|
+
"name"=>"30.009897,-81.387655",
|
18
|
+
"Placemark"=>
|
19
|
+
[{"AddressDetails"=>
|
20
|
+
{"Country"=>
|
21
|
+
{"AdministrativeArea"=>
|
22
|
+
{"Thoroughfare"=>{"ThoroughfareName"=>@attrs[:street]},
|
23
|
+
"PostalCode"=>{"PostalCodeNumber"=>@attrs[:zip]},
|
24
|
+
"AdministrativeAreaName"=>@attrs[:state]},
|
25
|
+
"CountryName"=>"USA",
|
26
|
+
"CountryNameCode"=>"US"},
|
27
|
+
"Accuracy"=>8},
|
28
|
+
"id"=>"p1",
|
29
|
+
"ExtendedData"=>
|
30
|
+
{"LatLonBox"=>
|
31
|
+
{"east"=>-81.3845068,
|
32
|
+
"south"=>30.0067498,
|
33
|
+
"west"=>-81.390802,
|
34
|
+
"north"=>30.013045}},
|
35
|
+
"Point"=>{"coordinates"=>[-81.3876544, 30.0098974, 0]},
|
36
|
+
"address"=> @attrs[:address]},
|
37
|
+
{"AddressDetails"=>
|
38
|
+
{"Country"=>
|
39
|
+
{"AdministrativeArea"=>
|
40
|
+
{"Locality"=>
|
41
|
+
{"LocalityName"=>@attrs[:city],
|
42
|
+
"PostalCode"=>{"PostalCodeNumber"=>@attrs[:zip]}},
|
43
|
+
"AdministrativeAreaName"=>"FL"},
|
44
|
+
"CountryName"=>"USA",
|
45
|
+
"CountryNameCode"=>"US"},
|
46
|
+
"Accuracy"=>5},
|
47
|
+
"id"=>"p2",
|
48
|
+
"ExtendedData"=>
|
49
|
+
{"LatLonBox"=>
|
50
|
+
{"east"=>-81.313069,
|
51
|
+
"south"=>29.929597,
|
52
|
+
"west"=>-81.498143,
|
53
|
+
"north"=>30.086469}},
|
54
|
+
"Point"=>{"coordinates"=>[-81.4059186, 29.9934528, 0]},
|
55
|
+
"address"=>"St Augustine, FL 32095, USA"},
|
56
|
+
{"AddressDetails"=>
|
57
|
+
{"Country"=>
|
58
|
+
{"AdministrativeArea"=>
|
59
|
+
{"AddressLine"=>["St Augustine"], "AdministrativeAreaName"=>"FL"},
|
60
|
+
"CountryName"=>"USA",
|
61
|
+
"CountryNameCode"=>"US"},
|
62
|
+
"Accuracy"=>4},
|
63
|
+
"id"=>"p3",
|
64
|
+
"ExtendedData"=>
|
65
|
+
{"LatLonBox"=>
|
66
|
+
{"east"=>-81.194405,
|
67
|
+
"south"=>29.767845,
|
68
|
+
"west"=>-81.63343,
|
69
|
+
"north"=>30.18062}},
|
70
|
+
"Point"=>{"coordinates"=>[-81.3839326, 30.0149544, 0]},
|
71
|
+
"address"=>"St Augustine, Florida, USA"},
|
72
|
+
{"AddressDetails"=>
|
73
|
+
{"Country"=>
|
74
|
+
{"AdministrativeArea"=>
|
75
|
+
{"AddressLine"=>[@attrs[:county]], "AdministrativeAreaName"=>"FL"},
|
76
|
+
"CountryName"=>"USA",
|
77
|
+
"CountryNameCode"=>"US"},
|
78
|
+
"Accuracy"=>3},
|
79
|
+
"id"=>"p4",
|
80
|
+
"ExtendedData"=>
|
81
|
+
{"LatLonBox"=>
|
82
|
+
{"east"=>-81.150818,
|
83
|
+
"south"=>29.622428,
|
84
|
+
"west"=>-81.69039,
|
85
|
+
"north"=>30.253036}},
|
86
|
+
"Point"=>{"coordinates"=>[-81.4278984, 29.9719419, 0]},
|
87
|
+
"address"=>"St Johns, Florida, USA"},
|
88
|
+
{"AddressDetails"=>
|
89
|
+
{"Country"=>
|
90
|
+
{"AdministrativeArea"=>{"AdministrativeAreaName"=>"FL"},
|
91
|
+
"CountryName"=>"USA",
|
92
|
+
"CountryNameCode"=>"US"},
|
93
|
+
"Accuracy"=>2},
|
94
|
+
"id"=>"p5",
|
95
|
+
"ExtendedData"=>
|
96
|
+
{"LatLonBox"=>
|
97
|
+
{"east"=>-79.974307,
|
98
|
+
"south"=>24.396308,
|
99
|
+
"west"=>-87.634643,
|
100
|
+
"north"=>31.001056}},
|
101
|
+
"Point"=>{"coordinates"=>[-81.5157535, 27.6648274, 0]},
|
102
|
+
"address"=>"Florida, USA"},
|
103
|
+
{"AddressDetails"=>
|
104
|
+
{"Country"=>{"CountryName"=>"USA", "CountryNameCode"=>"US"},
|
105
|
+
"Accuracy"=>1},
|
106
|
+
"id"=>"p6",
|
107
|
+
"ExtendedData"=>
|
108
|
+
{"LatLonBox"=>
|
109
|
+
{"east"=>-65.168504,
|
110
|
+
"south"=>17.83151,
|
111
|
+
"west"=>172.347848,
|
112
|
+
"north"=>71.434357}},
|
113
|
+
"Point"=>{"coordinates"=>[-95.712891, 37.09024, 0]},
|
114
|
+
"address"=>"United States"}]}
|
115
|
+
|
116
|
+
Net::HTTP.stub!(:get_response)
|
117
|
+
@reverse_geocode = ReverseGeocode.new(@attrs[:lat], @attrs[:long])
|
118
|
+
@reverse_geocode.stub!(:parse_json).and_return(@response)
|
119
|
+
end
|
120
|
+
|
121
|
+
%w( lat long address street state city zip county ).each do |attr|
|
122
|
+
describe "##{attr}" do
|
123
|
+
it {@reverse_geocode.send(attr).should == @attrs[attr.to_sym]}
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
describe "without a latitude or longitude" do
|
128
|
+
it "should raise an ArgumentError" do
|
129
|
+
lambda { ReverseGeocode.new(nil, 1) }.should raise_error(ArgumentError)
|
130
|
+
lambda { ReverseGeocode.new(1, nil) }.should raise_error(ArgumentError)
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
describe "when the response is a" do
|
135
|
+
def error_json(code)
|
136
|
+
{"Status"=>{"code"=>code, "request"=>"geocode"}, "name"=>""}
|
137
|
+
end
|
138
|
+
|
139
|
+
errors = {
|
140
|
+
400 => "Bad Request",
|
141
|
+
500 => "Server Error",
|
142
|
+
601 => "Missing Query or Address",
|
143
|
+
602 => "Unknown Address",
|
144
|
+
603 => "Unavailable Address",
|
145
|
+
604 => "Unknown Directions",
|
146
|
+
610 => "Bad Key",
|
147
|
+
620 => "Too Many Queries"
|
148
|
+
}
|
149
|
+
|
150
|
+
errors.each do |code, message|
|
151
|
+
describe code.to_s do
|
152
|
+
before do
|
153
|
+
@reverse_geocode.stub!(:parse_json).and_return(error_json(code))
|
154
|
+
end
|
155
|
+
|
156
|
+
it "should raise a GeocodeError" do
|
157
|
+
lambda {
|
158
|
+
@reverse_geocode.send(:handle_response)
|
159
|
+
}.should raise_error(ReverseGeocode::GeocodeError, "#{code}: #{message}")
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: hacked0ff-reverse_geocode
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Tommy Campbell & ReinH
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-03-20 00:00:00 -07:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: json
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 1.1.3
|
24
|
+
version:
|
25
|
+
description: A gem that provides Reverse Geocoding using the Google Maps API
|
26
|
+
email: tommycampbell@mindspring.com
|
27
|
+
executables: []
|
28
|
+
|
29
|
+
extensions: []
|
30
|
+
|
31
|
+
extra_rdoc_files:
|
32
|
+
- README
|
33
|
+
- LICENSE
|
34
|
+
- TODO
|
35
|
+
files:
|
36
|
+
- LICENSE
|
37
|
+
- README
|
38
|
+
- Rakefile
|
39
|
+
- TODO
|
40
|
+
- lib/reverse_geocode.rb
|
41
|
+
- spec/reverse_geocode_spec.rb
|
42
|
+
- spec/spec_helper.rb
|
43
|
+
has_rdoc: true
|
44
|
+
homepage: http://example.com
|
45
|
+
post_install_message:
|
46
|
+
rdoc_options: []
|
47
|
+
|
48
|
+
require_paths:
|
49
|
+
- lib
|
50
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: "0"
|
55
|
+
version:
|
56
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: "0"
|
61
|
+
version:
|
62
|
+
requirements: []
|
63
|
+
|
64
|
+
rubyforge_project:
|
65
|
+
rubygems_version: 1.2.0
|
66
|
+
signing_key:
|
67
|
+
specification_version: 2
|
68
|
+
summary: A gem that provides Reverse Geocoding using the Google Maps API
|
69
|
+
test_files: []
|
70
|
+
|