rack-geo 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +9 -0
- data/HISTORY.rdoc +3 -0
- data/LICENSE.txt +7 -0
- data/README.rdoc +21 -0
- data/Rakefile +49 -0
- data/lib/rack-geo.rb +1 -0
- data/lib/rack/geo.rb +94 -0
- data/lib/rack/geo/version.rb +11 -0
- data/spec/rack/geo_spec.rb +258 -0
- data/spec/spec.opts +4 -0
- data/spec/spec_helper.rb +7 -0
- metadata +129 -0
data/.gitignore
ADDED
data/HISTORY.rdoc
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
Copyright © 2010 Square, Inc.
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
4
|
+
|
5
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
6
|
+
|
7
|
+
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
= Rack::Geo
|
2
|
+
|
3
|
+
Rack middleware for parsing and serializing IETF draft {Geo-Position}[http://tools.ietf.org/html/draft-daviel-http-geo-header-05] HTTP headers.
|
4
|
+
|
5
|
+
== Prerequisites
|
6
|
+
|
7
|
+
* {Rack}[http://rack.rubyforge.org/]
|
8
|
+
|
9
|
+
== Testing
|
10
|
+
|
11
|
+
Testing requires the RSpec gem:
|
12
|
+
|
13
|
+
* {Rspec}[http://rspec.info/]
|
14
|
+
|
15
|
+
To test, run:
|
16
|
+
`rake`
|
17
|
+
|
18
|
+
== License
|
19
|
+
|
20
|
+
Copyright © 2010 Square, Inc.
|
21
|
+
See LICENSE.txt in this directory.
|
data/Rakefile
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
require 'spec/rake/spectask'
|
4
|
+
|
5
|
+
require File.join(File.dirname(__FILE__), 'lib', 'rack', 'geo', 'version')
|
6
|
+
|
7
|
+
begin
|
8
|
+
require 'jeweler'
|
9
|
+
Jeweler::Tasks.new do |gemspec|
|
10
|
+
gemspec.version = Rack::Geo::VERSION::STRING
|
11
|
+
gemspec.name = "rack-geo"
|
12
|
+
gemspec.summary = "Rack middleware for Geo-Position HTTP headers"
|
13
|
+
gemspec.description = "Parse and serialize geospatial HTTP headers."
|
14
|
+
gemspec.email = "github@squareup.com"
|
15
|
+
gemspec.homepage = "http://github.com/square/rack-geo"
|
16
|
+
gemspec.authors = [
|
17
|
+
"Randy Reddig",
|
18
|
+
"Cameron Walters",
|
19
|
+
"Paul McKellar",
|
20
|
+
]
|
21
|
+
gemspec.extra_rdoc_files = [
|
22
|
+
'README.rdoc',
|
23
|
+
'HISTORY.rdoc',
|
24
|
+
'LICENSE.txt',
|
25
|
+
]
|
26
|
+
gemspec.add_dependency "rack", ">=1.0.0"
|
27
|
+
gemspec.add_development_dependency "rack-test", ">=0.5.3"
|
28
|
+
gemspec.add_development_dependency "rspec", ">=1.3.0"
|
29
|
+
end
|
30
|
+
rescue LoadError
|
31
|
+
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
32
|
+
end
|
33
|
+
|
34
|
+
desc "Run all specs"
|
35
|
+
Spec::Rake::SpecTask.new do |t|
|
36
|
+
t.spec_opts = ["--options", "spec/spec.opts"]
|
37
|
+
t.spec_files = FileList["spec/**/*_spec.rb"]
|
38
|
+
t.rcov = ENV["RCOV"]
|
39
|
+
t.rcov_opts = %w{--exclude osx\/objc,gems\/,spec\/}
|
40
|
+
t.verbose = true
|
41
|
+
end
|
42
|
+
|
43
|
+
task :spec => :check_dependencies
|
44
|
+
task :default => :spec
|
45
|
+
|
46
|
+
desc "Remove trailing whitespace"
|
47
|
+
task :whitespace do
|
48
|
+
sh %{find . -name '*.rb' -exec sed -i '' 's/ *$//g' {} \\;}
|
49
|
+
end
|
data/lib/rack-geo.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'rack/geo'
|
data/lib/rack/geo.rb
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
require 'rack/geo/version'
|
2
|
+
|
3
|
+
module Rack
|
4
|
+
class Geo
|
5
|
+
def initialize(app)
|
6
|
+
@app = app
|
7
|
+
end
|
8
|
+
|
9
|
+
def call(env)
|
10
|
+
position = Position.new(env["HTTP_GEO_POSITION"] || env["HTTP_X_GEO_POSITION"])
|
11
|
+
env["geo.position"] = position if position.valid?
|
12
|
+
@app.call(env)
|
13
|
+
end
|
14
|
+
|
15
|
+
class Position
|
16
|
+
attr_accessor :latitude, :longitude, :altitude, :uncertainty, :heading, :speed
|
17
|
+
|
18
|
+
def initialize(value=nil)
|
19
|
+
parse! value
|
20
|
+
end
|
21
|
+
|
22
|
+
MATCH_LLA = /\A([+-]?[0-9\.]+);([+-]?[0-9\.]+)(?:;([+-]?[0-9\.]+))?/.freeze
|
23
|
+
MATCH_EPU = /\sepu=([0-9\.]+)(?:\s|\z)/i.freeze
|
24
|
+
MATCH_HDN = /\shdn=([0-9\.]+)(?:\s|\z)/i.freeze
|
25
|
+
MATCH_SPD = /\sspd=([0-9\.]+)(?:\s|\z)/i.freeze
|
26
|
+
|
27
|
+
# Parse Geo-Position header:
|
28
|
+
# http://tools.ietf.org/html/draft-daviel-http-geo-header-05
|
29
|
+
def parse!(value)
|
30
|
+
reset!
|
31
|
+
value = value.to_s.strip
|
32
|
+
|
33
|
+
if lla = MATCH_LLA.match(value)
|
34
|
+
@latitude = lla[1].to_f
|
35
|
+
@longitude = lla[2].to_f
|
36
|
+
@altitude = lla[3].to_f if lla[3]
|
37
|
+
end
|
38
|
+
|
39
|
+
if epu = MATCH_EPU.match(value)
|
40
|
+
@uncertainty = epu[1].to_f
|
41
|
+
end
|
42
|
+
|
43
|
+
if hdn = MATCH_HDN.match(value)
|
44
|
+
@heading = hdn[1].to_f
|
45
|
+
end
|
46
|
+
|
47
|
+
if spd = MATCH_SPD.match(value)
|
48
|
+
@speed = spd[1].to_f
|
49
|
+
end
|
50
|
+
|
51
|
+
nil
|
52
|
+
end
|
53
|
+
|
54
|
+
def valid?
|
55
|
+
(!latitude.nil? && latitude.respond_to?(:to_f) && (-90..90).include?(latitude.to_f)) &&
|
56
|
+
(!longitude.nil? && longitude.respond_to?(:to_f) && (-180..180).include?(longitude.to_f)) &&
|
57
|
+
(altitude.nil? || altitude.respond_to?(:to_f)) &&
|
58
|
+
(uncertainty.nil? || uncertainty.respond_to?(:to_f) && uncertainty.to_f >= 0) &&
|
59
|
+
(heading.nil? || heading.respond_to?(:to_f) && (0..360).include?(heading.to_f)) &&
|
60
|
+
(speed.nil? || speed.respond_to?(:to_f) && speed.to_f >= 0)
|
61
|
+
end
|
62
|
+
|
63
|
+
def attributes
|
64
|
+
{
|
65
|
+
:latitude => latitude,
|
66
|
+
:longitude => longitude,
|
67
|
+
:altitude => altitude,
|
68
|
+
:uncertainty => uncertainty,
|
69
|
+
:heading => heading,
|
70
|
+
:speed => speed,
|
71
|
+
}
|
72
|
+
end
|
73
|
+
|
74
|
+
def to_http_header
|
75
|
+
value = "%f;%f" % [latitude.to_f, longitude.to_f]
|
76
|
+
value += ";%f" % altitude.to_f if altitude
|
77
|
+
value += " epu=%f" % uncertainty.to_f if uncertainty
|
78
|
+
value += " hdn=%f" % heading.to_f if heading
|
79
|
+
value += " spd=%f" % speed.to_f if speed
|
80
|
+
value
|
81
|
+
end
|
82
|
+
|
83
|
+
def self.from_http_header(value)
|
84
|
+
self.new(value)
|
85
|
+
end
|
86
|
+
|
87
|
+
private
|
88
|
+
|
89
|
+
def reset!
|
90
|
+
@latitude = @longitude = @altitude = @uncertainty = @heading = @speed = nil
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,258 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Rack::Geo do
|
4
|
+
def setup_request(header_name="HTTP_GEO_POSITION")
|
5
|
+
@request = Rack::MockRequest.env_for("/", header_name => @coords, :lint => true, :fatal => true)
|
6
|
+
end
|
7
|
+
|
8
|
+
before :each do
|
9
|
+
@latitude, @longitude, @uncertainty = 37.0625, -95.677068, 100
|
10
|
+
@coords = "#{@latitude};#{@longitude} epu=#{@uncertainty}"
|
11
|
+
@app = lambda { |env| [200, {"Content-Type" => "text/plain"}, [""]] }
|
12
|
+
end
|
13
|
+
|
14
|
+
["HTTP_GEO_POSITION", "HTTP_X_GEO_POSITION"].each do |header_name|
|
15
|
+
describe "with invalid geo position header '#{header_name}'" do
|
16
|
+
before :each do
|
17
|
+
setup_request(header_name)
|
18
|
+
Rack::Geo::Position.stub!(:new).and_return(mock(Rack::Geo::Position, :valid? => false))
|
19
|
+
@status, @headers, @response = described_class.new(@app).call(@request)
|
20
|
+
end
|
21
|
+
|
22
|
+
it "does not assign a Rack::Geo::Position instance to env['geo.position']" do
|
23
|
+
@request['geo.position'].should be_nil
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "with valid geo position header '#{header_name}: #{@coords}'" do
|
28
|
+
before :each do
|
29
|
+
setup_request(header_name)
|
30
|
+
@status, @headers, @response = described_class.new(@app).call(@request)
|
31
|
+
end
|
32
|
+
|
33
|
+
it "assigns a Rack::Geo::Position instance to env['geo.position']" do
|
34
|
+
@request['geo.position'].should be_an_instance_of(Rack::Geo::Position)
|
35
|
+
end
|
36
|
+
|
37
|
+
it "the Rack::Geo::Position instance should reflect the header value" do
|
38
|
+
@request['geo.position'].latitude.should == @latitude
|
39
|
+
@request['geo.position'].longitude.should == @longitude
|
40
|
+
@request['geo.position'].uncertainty.should == @uncertainty
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
describe Rack::Geo::Position do
|
48
|
+
|
49
|
+
ZEROES = %w[0 -0 +0 0.0 -0.0 +0.0]
|
50
|
+
LATITUDES = %w[-90 -45 0 45 +45 90 +90]
|
51
|
+
LONGITUDES = %w[-180 -90 -45 0 45 +45 90 +90 180 +180]
|
52
|
+
ALTITUDES = %w[-85.5 -34 0 15 1337 8848 23300.0 +23300.0]
|
53
|
+
UNCERTAINTIES = %w[0 0.0 0.00 1.25 32.1 455 600.123]
|
54
|
+
HEADINGS = %w[0 0.0 0.00 1.25 32.1 180 359.123 360]
|
55
|
+
SPEEDS = %w[0 0.0 0.00 1.25 32.1 999 9999.99 12345.6456]
|
56
|
+
|
57
|
+
describe "#new" do
|
58
|
+
it "creates an instance of #{described_class}" do
|
59
|
+
instance = described_class.new
|
60
|
+
instance.should be_an_instance_of(described_class)
|
61
|
+
end
|
62
|
+
|
63
|
+
it "calls #parse!" do
|
64
|
+
class GeoPositionParseTest < described_class
|
65
|
+
def parse!(arg)
|
66
|
+
@parsed = arg
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
instance = GeoPositionParseTest.new "TEST"
|
71
|
+
instance.instance_variable_get(:@parsed).should == "TEST"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe "#from_http_header" do
|
76
|
+
it "creates an instance of #{described_class}" do
|
77
|
+
instance = described_class.from_http_header nil
|
78
|
+
instance.should be_an_instance_of(described_class)
|
79
|
+
end
|
80
|
+
|
81
|
+
it "calls #new with supplied argument" do
|
82
|
+
described_class.should_receive(:new).with("TEST")
|
83
|
+
described_class.from_http_header "TEST"
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
describe "instance method" do
|
88
|
+
before :each do
|
89
|
+
@instance = described_class.new
|
90
|
+
end
|
91
|
+
|
92
|
+
describe "#attributes" do
|
93
|
+
it "returns a hash" do
|
94
|
+
@instance.attributes.should be_an_instance_of(Hash)
|
95
|
+
end
|
96
|
+
|
97
|
+
it "returns a hash containing specific keys" do
|
98
|
+
h = @instance.attributes
|
99
|
+
[:latitude, :longitude, :altitude, :uncertainty, :heading, :speed].each do |key|
|
100
|
+
h.should have_key(key)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
describe "#parse!" do
|
106
|
+
it "nil sets all attributes to nil" do
|
107
|
+
@instance.parse! nil
|
108
|
+
@instance.latitude.should == nil
|
109
|
+
@instance.longitude.should == nil
|
110
|
+
@instance.altitude.should == nil
|
111
|
+
@instance.uncertainty.should == nil
|
112
|
+
@instance.heading.should == nil
|
113
|
+
@instance.speed.should == nil
|
114
|
+
end
|
115
|
+
|
116
|
+
it "\"0;0\" parses latitude and longitude" do
|
117
|
+
@instance.parse! "0;0"
|
118
|
+
@instance.latitude.should == 0.0
|
119
|
+
@instance.longitude.should == 0.0
|
120
|
+
@instance.altitude.should == nil
|
121
|
+
@instance.uncertainty.should == nil
|
122
|
+
@instance.heading.should == nil
|
123
|
+
@instance.speed.should == nil
|
124
|
+
end
|
125
|
+
|
126
|
+
it "\"0;0;0\" parses latitude, longitude and altitude" do
|
127
|
+
@instance.parse! "0;0;0"
|
128
|
+
@instance.latitude.should == 0.0
|
129
|
+
@instance.longitude.should == 0.0
|
130
|
+
@instance.altitude.should == 0.0
|
131
|
+
@instance.uncertainty.should == nil
|
132
|
+
@instance.heading.should == nil
|
133
|
+
@instance.speed.should == nil
|
134
|
+
end
|
135
|
+
|
136
|
+
ZEROES.each do |latitude|
|
137
|
+
ZEROES.each do |longitude|
|
138
|
+
value = "#{latitude};#{longitude}"
|
139
|
+
it "\"#{value}\" should return a new instance with latitude == 0 and longitude == 0" do
|
140
|
+
@instance.parse! value
|
141
|
+
@instance.latitude.should == 0.0
|
142
|
+
@instance.longitude.should == 0.0
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
LATITUDES.each do |latitude|
|
148
|
+
LONGITUDES.each do |longitude|
|
149
|
+
value = "#{latitude};#{longitude}"
|
150
|
+
latitude_f = latitude.to_f
|
151
|
+
longitude_f = longitude.to_f
|
152
|
+
it "#{value} should return a new instance with latitude == #{latitude_f} and longitude == #{longitude_f}" do
|
153
|
+
@instance.parse! value
|
154
|
+
@instance.latitude.should == latitude_f
|
155
|
+
@instance.longitude.should == longitude_f
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
LATITUDES.each do |latitude|
|
161
|
+
LONGITUDES.each do |longitude|
|
162
|
+
ALTITUDES.each do |altitude|
|
163
|
+
value = "#{latitude};#{longitude};#{altitude}"
|
164
|
+
latitude_f = latitude.to_f
|
165
|
+
longitude_f = longitude.to_f
|
166
|
+
altitude_f = altitude.to_f
|
167
|
+
it "#{value} should return a new instance with latitude == #{latitude_f}, longitude == #{longitude_f} and altitude == #{altitude_f}" do
|
168
|
+
@instance.parse! value
|
169
|
+
@instance.latitude.should == latitude_f
|
170
|
+
@instance.longitude.should == longitude_f
|
171
|
+
@instance.altitude.should == altitude_f
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
UNCERTAINTIES.each do |uncertainty|
|
178
|
+
value = "0;0;0 epu=#{uncertainty}"
|
179
|
+
uncertainty_f = uncertainty.to_f
|
180
|
+
it "\"#{value}\" should return a new instance with uncertainty = #{uncertainty_f}" do
|
181
|
+
@instance.parse! value
|
182
|
+
@instance.uncertainty.should == uncertainty_f
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
HEADINGS.each do |heading|
|
187
|
+
value = "0;0;0 hdn=#{heading}"
|
188
|
+
heading_f = heading.to_f
|
189
|
+
it "\"#{value}\" should return a new instance with heading = #{heading_f}" do
|
190
|
+
@instance.parse! value
|
191
|
+
@instance.heading.should == heading_f
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
SPEEDS.each do |speed|
|
196
|
+
value = "0;0;0 spd=#{speed}"
|
197
|
+
speed_f = speed.to_f
|
198
|
+
it "\"#{value}\" should return a new instance with speed = #{speed_f}" do
|
199
|
+
@instance.parse! value
|
200
|
+
@instance.speed.should == speed_f
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
describe "#valid?" do
|
206
|
+
before :each do
|
207
|
+
@instance = described_class.new "0;0;0 epu=0 hdn=0 spd=0"
|
208
|
+
@instance.should be_valid
|
209
|
+
end
|
210
|
+
|
211
|
+
it "returns false for instances initialized with no arguments" do
|
212
|
+
described_class.new.should_not be_valid
|
213
|
+
end
|
214
|
+
|
215
|
+
[nil, false, [], {}, -91, 90.0001, "-90.0001", "91"].each do |latitude|
|
216
|
+
it "returns false when latitude = #{latitude.inspect}" do
|
217
|
+
@instance.latitude = latitude
|
218
|
+
@instance.should_not be_valid
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
[nil, false, [], {}, -181, 180.0001, "-180.0001", "181"].each do |longitude|
|
223
|
+
it "returns false when longitude = #{longitude.inspect}" do
|
224
|
+
@instance.longitude = longitude
|
225
|
+
@instance.should_not be_valid
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
[false, [], {}].each do |altitude|
|
230
|
+
it "returns false when altitude = #{altitude.inspect}" do
|
231
|
+
@instance.altitude = altitude
|
232
|
+
@instance.should_not be_valid
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
[false, [], {}, -1, -0.0001, "-0.0001"].each do |uncertainty|
|
237
|
+
it "returns false when uncertainty = #{uncertainty.inspect}" do
|
238
|
+
@instance.uncertainty = uncertainty
|
239
|
+
@instance.should_not be_valid
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
[false, [], {}, -1, -0.0001, 360.01, 361, "-0.0001", "360.01", "361"].each do |heading|
|
244
|
+
it "returns false when heading = #{heading.inspect}" do
|
245
|
+
@instance.heading = heading
|
246
|
+
@instance.should_not be_valid
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
[false, [], {}, -1, -0.0001, "-0.0001"].each do |speed|
|
251
|
+
it "returns false when speed = #{speed.inspect}" do
|
252
|
+
@instance.speed = speed
|
253
|
+
@instance.should_not be_valid
|
254
|
+
end
|
255
|
+
end
|
256
|
+
end
|
257
|
+
end
|
258
|
+
end
|
data/spec/spec.opts
ADDED
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,129 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rack-geo
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 27
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
- 0
|
10
|
+
version: 0.1.0
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Randy Reddig
|
14
|
+
- Cameron Walters
|
15
|
+
- Paul McKellar
|
16
|
+
autorequire:
|
17
|
+
bindir: bin
|
18
|
+
cert_chain: []
|
19
|
+
|
20
|
+
date: 2010-07-18 00:00:00 -07:00
|
21
|
+
default_executable:
|
22
|
+
dependencies:
|
23
|
+
- !ruby/object:Gem::Dependency
|
24
|
+
name: rack
|
25
|
+
prerelease: false
|
26
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
27
|
+
none: false
|
28
|
+
requirements:
|
29
|
+
- - ">="
|
30
|
+
- !ruby/object:Gem::Version
|
31
|
+
hash: 23
|
32
|
+
segments:
|
33
|
+
- 1
|
34
|
+
- 0
|
35
|
+
- 0
|
36
|
+
version: 1.0.0
|
37
|
+
type: :runtime
|
38
|
+
version_requirements: *id001
|
39
|
+
- !ruby/object:Gem::Dependency
|
40
|
+
name: rack-test
|
41
|
+
prerelease: false
|
42
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
43
|
+
none: false
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
hash: 13
|
48
|
+
segments:
|
49
|
+
- 0
|
50
|
+
- 5
|
51
|
+
- 3
|
52
|
+
version: 0.5.3
|
53
|
+
type: :development
|
54
|
+
version_requirements: *id002
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
prerelease: false
|
58
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
59
|
+
none: false
|
60
|
+
requirements:
|
61
|
+
- - ">="
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
hash: 27
|
64
|
+
segments:
|
65
|
+
- 1
|
66
|
+
- 3
|
67
|
+
- 0
|
68
|
+
version: 1.3.0
|
69
|
+
type: :development
|
70
|
+
version_requirements: *id003
|
71
|
+
description: Parse and serialize geospatial HTTP headers.
|
72
|
+
email: github@squareup.com
|
73
|
+
executables: []
|
74
|
+
|
75
|
+
extensions: []
|
76
|
+
|
77
|
+
extra_rdoc_files:
|
78
|
+
- HISTORY.rdoc
|
79
|
+
- LICENSE.txt
|
80
|
+
- README.rdoc
|
81
|
+
files:
|
82
|
+
- .gitignore
|
83
|
+
- HISTORY.rdoc
|
84
|
+
- LICENSE.txt
|
85
|
+
- README.rdoc
|
86
|
+
- Rakefile
|
87
|
+
- lib/rack-geo.rb
|
88
|
+
- lib/rack/geo.rb
|
89
|
+
- lib/rack/geo/version.rb
|
90
|
+
- spec/rack/geo_spec.rb
|
91
|
+
- spec/spec.opts
|
92
|
+
- spec/spec_helper.rb
|
93
|
+
has_rdoc: true
|
94
|
+
homepage: http://github.com/square/rack-geo
|
95
|
+
licenses: []
|
96
|
+
|
97
|
+
post_install_message:
|
98
|
+
rdoc_options:
|
99
|
+
- --charset=UTF-8
|
100
|
+
require_paths:
|
101
|
+
- lib
|
102
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
103
|
+
none: false
|
104
|
+
requirements:
|
105
|
+
- - ">="
|
106
|
+
- !ruby/object:Gem::Version
|
107
|
+
hash: 3
|
108
|
+
segments:
|
109
|
+
- 0
|
110
|
+
version: "0"
|
111
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
112
|
+
none: false
|
113
|
+
requirements:
|
114
|
+
- - ">="
|
115
|
+
- !ruby/object:Gem::Version
|
116
|
+
hash: 3
|
117
|
+
segments:
|
118
|
+
- 0
|
119
|
+
version: "0"
|
120
|
+
requirements: []
|
121
|
+
|
122
|
+
rubyforge_project:
|
123
|
+
rubygems_version: 1.3.7
|
124
|
+
signing_key:
|
125
|
+
specification_version: 3
|
126
|
+
summary: Rack middleware for Geo-Position HTTP headers
|
127
|
+
test_files:
|
128
|
+
- spec/rack/geo_spec.rb
|
129
|
+
- spec/spec_helper.rb
|