http_router_sinatra 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.
@@ -0,0 +1,3 @@
1
+ pkg/*
2
+ *.gem
3
+ .bundle
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in http_router_sinatra.gemspec
4
+ gemspec
@@ -0,0 +1,45 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ http_router_sinatra (0.0.1)
5
+ http_router (~> 0.6.1)
6
+ sinatra (~> 1.2.0)
7
+
8
+ GEM
9
+ remote: http://rubygems.org/
10
+ specs:
11
+ callsite (0.0.4)
12
+ code_stats (0.0.1)
13
+ dirge (>= 0.0.3)
14
+ rainbow
15
+ dirge (0.0.5)
16
+ callsite (>= 0.0.2)
17
+ http_router (0.6.1)
18
+ rack (>= 1.0.0)
19
+ url_mount (~> 0.2.1)
20
+ minitest (2.0.2)
21
+ phocus (1.1)
22
+ rack (1.2.2)
23
+ rainbow (1.1)
24
+ rake (0.8.7)
25
+ rbench (0.2.3)
26
+ sinatra (1.2.1)
27
+ rack (~> 1.1)
28
+ tilt (>= 1.2.2, < 2.0)
29
+ tilt (1.2.2)
30
+ url_mount (0.2.1)
31
+ rack
32
+
33
+ PLATFORMS
34
+ ruby
35
+
36
+ DEPENDENCIES
37
+ bundler (~> 1.0.0)
38
+ code_stats
39
+ http_router (~> 0.6.1)
40
+ http_router_sinatra!
41
+ minitest (~> 2.0.0)
42
+ phocus
43
+ rake
44
+ rbench
45
+ sinatra (~> 1.2.0)
@@ -0,0 +1,10 @@
1
+ # HttpRouter for Sinatra
2
+
3
+ ## Usage
4
+
5
+ In your Sinatra app, register your extension
6
+
7
+ register HttpRouter::Sinatra::Extension
8
+
9
+ Then, add your routes normally. If you use the :name option when defining your route, you can later generate your route
10
+ with the `generate` method.
@@ -0,0 +1,21 @@
1
+ require 'bundler'
2
+ require 'code_stats'
3
+
4
+ desc "Run tests"
5
+ task :test do
6
+ $: << 'lib'
7
+ require 'http_router_sinatra'
8
+ require 'test/helper'
9
+ Dir['test/**/test_*.rb'].each { |test| require test }
10
+ end
11
+
12
+ require 'rake/rdoctask'
13
+ desc "Generate documentation"
14
+ Rake::RDocTask.new do |rd|
15
+ rd.main = "README.rdoc"
16
+ rd.rdoc_files.include("README.rdoc", "lib/**/*.rb")
17
+ rd.rdoc_dir = 'rdoc'
18
+ end
19
+
20
+ Bundler::GemHelper.install_tasks
21
+ CodeStats::Tasks.new(:reporting_depth => 3)
@@ -0,0 +1,30 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "http_router_sinatra/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "http_router_sinatra"
7
+ s.version = HttpRouter::Sinatra::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Joshua Hull"]
10
+ s.email = ["joshbuddy@gmail.com"]
11
+ s.homepage = "https://github.com/joshbuddy/http_router_sinatra"
12
+ s.summary = %q{Kick ass router for Sinatra based on http_router}
13
+ s.description = %q{Kick ass router for Sinatra based on http_router.}
14
+
15
+ s.rubyforge_project = "http_router_sinatra"
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+ s.require_paths = ["lib"]
21
+
22
+ s.add_dependency "http_router", "~> 0.6.2"
23
+ s.add_dependency "sinatra", "~> 1.2.0"
24
+ s.add_development_dependency 'minitest', '~> 2.0.0'
25
+ s.add_development_dependency 'code_stats'
26
+ s.add_development_dependency 'rake'
27
+ s.add_development_dependency 'rbench'
28
+ s.add_development_dependency 'phocus'
29
+ s.add_development_dependency 'bundler', '~> 1.0.0'
30
+ end
@@ -0,0 +1,189 @@
1
+ require 'http_router'
2
+ require 'sinatra'
3
+
4
+ class HttpRouter
5
+ class Sinatra
6
+
7
+ def initialize
8
+ ::Sinatra.send(:include, Extension)
9
+ end
10
+
11
+ module Extension
12
+
13
+ def self.registered(app)
14
+ app.send(:include, Extension)
15
+ end
16
+
17
+ def self.included(base)
18
+ base.extend ClassMethods
19
+ end
20
+
21
+ def generate(name, *params)
22
+ self.class.generate(name, *params)
23
+ end
24
+
25
+ private
26
+ def route!(base=self.class, pass_block=nil)
27
+ request.env['sinatra.instance'] = self
28
+ if base.router and match = base.router.recognize(request.env)
29
+ if match.respond_to?(:path)
30
+ throw :halt, @_response_buffer
31
+ elsif match.is_a?(Array)
32
+ route_eval {
33
+ match[1].each{|k,v| response[k] = v}
34
+ status match[0]
35
+ }
36
+ end
37
+ end
38
+
39
+ # Run routes defined in superclass.
40
+ if base.superclass.respond_to?(:router)
41
+ route! base.superclass, pass_block
42
+ return
43
+ end
44
+
45
+ route_eval(&pass_block) if pass_block
46
+
47
+ route_missing
48
+ ensure
49
+ @_response_buffer = nil
50
+ end
51
+
52
+ module ClassMethods
53
+
54
+ def new(*args, &bk)
55
+ configure! unless @_configured
56
+ super(*args, &bk)
57
+ end
58
+
59
+ def get(path, *args, &block)
60
+ conditions = @conditions.dup
61
+ route('GET', path, *args, &block)
62
+
63
+ @conditions = conditions
64
+ route('HEAD', path, *args, &block)
65
+ end
66
+
67
+ def put(path, *args, &bk); route 'PUT', path, *args, &bk end
68
+ def post(path, *args, &bk); route 'POST', path, *args, &bk end
69
+ def delete(path, *args, &bk); route 'DELETE', path, *args, &bk end
70
+ def head(path, *args, &bk); route 'HEAD', path, *args, &bk end
71
+
72
+ def route(verb, path, options={}, &block)
73
+ name = options.delete(:name)
74
+
75
+ path = transform_path(path)
76
+
77
+ define_method "#{verb} #{path}", &block
78
+ unbound_method = instance_method("#{verb} #{path}")
79
+ block = block.arity.zero? ?
80
+ proc { unbound_method.bind(self).call } :
81
+ proc { unbound_method.bind(self).call(*@block_params) }
82
+
83
+ invoke_hook(:route_added, verb, path, block)
84
+
85
+ route = router.add(path)
86
+
87
+ route.matching(options[:matching]) if options.key?(:matching)
88
+
89
+ route.send(verb.downcase.to_sym)
90
+ route.host(options[:host]) if options.key?(:host)
91
+
92
+ route.name(name) if name
93
+
94
+ route.arbitrary_with_continue do |req, params|
95
+ if req.testing_405?
96
+ req.continue[true]
97
+ else
98
+ req.rack_request.env['sinatra.instance'].instance_eval do
99
+ handled = false
100
+ @block_params = req.params
101
+ (@params ||= {}).merge!(params)
102
+ pass_block = catch(:pass) do
103
+ route_eval(&block)
104
+ handled = true
105
+ end
106
+ req.continue[handled]
107
+ end
108
+ end
109
+ end
110
+
111
+ route.to(block)
112
+ route
113
+ end
114
+
115
+ def router
116
+ @router ||= HttpRouter.new
117
+ yield(@router) if block_given?
118
+ @router
119
+ end
120
+
121
+ def generate(name, *params)
122
+ router.url(name, *params)
123
+ end
124
+
125
+ def reset!
126
+ router.reset!
127
+ super
128
+ end
129
+
130
+ def configure!
131
+ configure :development do
132
+ error 404 do
133
+ content_type 'text/html'
134
+
135
+ (<<-HTML).gsub(/^ {17}/, '')
136
+ <!DOCTYPE html>
137
+ <html>
138
+ <head>
139
+ <style type="text/css">
140
+ body { text-align:center;font-family:helvetica,arial;font-size:22px;
141
+ color:#888;margin:20px}
142
+ #c {margin:0 auto;width:500px;text-align:left}
143
+ </style>
144
+ </head>
145
+ <body>
146
+ <h2>Sinatra doesn't know this ditty.</h2>
147
+ <div id="c">
148
+ Try this:
149
+ <pre>#{request.request_method.downcase} '#{request.path_info}' do\n "Hello World"\nend</pre>
150
+ </div>
151
+ </body>
152
+ </html>
153
+ HTML
154
+ end
155
+ error 405 do
156
+ content_type 'text/html'
157
+
158
+ (<<-HTML).gsub(/^ {17}/, '')
159
+ <!DOCTYPE html>
160
+ <html>
161
+ <head>
162
+ <style type="text/css">
163
+ body { text-align:center;font-family:helvetica,arial;font-size:22px;
164
+ color:#888;margin:20px}
165
+ #c {margin:0 auto;width:500px;text-align:left}
166
+ </style>
167
+ </head>
168
+ <body>
169
+ <h2>Sinatra sorta knows this ditty, but the request method is not allowed.</h2>
170
+ </body>
171
+ </html>
172
+ HTML
173
+ end
174
+ end
175
+
176
+ @_configured = true
177
+ end
178
+
179
+ private
180
+ def transform_path(path)
181
+ if path.is_a?(String)
182
+ path.gsub!(/\/\?$/, '(/)')
183
+ end
184
+ path
185
+ end
186
+ end # ClassMethods
187
+ end # Extension
188
+ end # Sinatra
189
+ end # HttpRouter
@@ -0,0 +1,5 @@
1
+ class HttpRouter
2
+ class Sinatra
3
+ VERSION = "0.0.1"
4
+ end
5
+ end
@@ -0,0 +1,74 @@
1
+ require 'minitest/autorun'
2
+ require 'phocus'
3
+
4
+ class HttpRouter::Route
5
+ def default_destination
6
+ to{|env| Rack::Response.new("Routing to #{to_s}").finish}
7
+ end
8
+ end
9
+
10
+ class MiniTest::Unit::TestCase
11
+ def router(*args, &blk)
12
+ @router ||= HttpRouter.new(*args, &blk)
13
+ if blk
14
+ @router.routes.each do |route|
15
+ route.default_destination if route.dest.nil?
16
+ end
17
+ @router.routes.size > 1 ? @router.routes : @router.routes.first
18
+ else
19
+ @router
20
+ end
21
+ end
22
+
23
+ def assert_body(expect, response)
24
+ response = router.call(response) if response.is_a?(Hash)
25
+ body = case expect
26
+ when Array then []
27
+ when String then ""
28
+ else raise
29
+ end
30
+ response.last.each {|p| body << p}
31
+ assert_equal expect, body
32
+ end
33
+
34
+ def assert_header(header, response)
35
+ response = router.call(response) if response.is_a?(Hash)
36
+ header.each{|k, v| assert_equal v, response[1][k]}
37
+ end
38
+
39
+ def assert_status(status, response)
40
+ response = router.call(response) if response.is_a?(Hash)
41
+ assert_equal status, response.first
42
+ end
43
+
44
+ def assert_route(route, request, params = nil, &blk)
45
+ if route.is_a?(String)
46
+ router.reset!
47
+ route = router.add(route)
48
+ end
49
+ route.to{|env| Rack::Response.new("Routing to #{route.to_s}").finish} if route && !route.compiled?
50
+ request = Rack::MockRequest.env_for(request) if request.is_a?(String)
51
+ response = @router.call(request)
52
+ if route
53
+ dest = "Routing to #{route.to_s}"
54
+ assert_equal [dest], response.last.body
55
+ if params
56
+ assert_equal params.size, request['router.params'].size
57
+ params.each { |k, v| assert_equal v, request['router.params'][k] }
58
+ elsif !request['router.params'].nil? and !request['router.params'].empty?
59
+ raise "Wasn't expecting any parameters, got #{request['router.params'].inspect}"
60
+ end
61
+ else
62
+ assert_equal 404, response.first
63
+ end
64
+ end
65
+
66
+ def assert_generate(path, route, *args)
67
+ if route.is_a?(String)
68
+ router.reset!
69
+ route = router.add(route).to(path.to_sym)
70
+ end
71
+ route.to{|env| Rack::Response.new("Routing to #{route.to_s}").finish} if route.respond_to?(:compiled?) && !route.compiled?
72
+ assert_equal path, router.url(route, *args)
73
+ end
74
+ end
@@ -0,0 +1,145 @@
1
+ module CallWithMockRequestMixin
2
+ def call_with_mock_request(url = "/sample", method = "GET")
3
+ Rack::MockRequest.new(self).request(method, url)
4
+ end
5
+ end
6
+
7
+ class TestRecognize < MiniTest::Unit::TestCase
8
+
9
+ def setup
10
+ @app = Sinatra.new { register HttpRouter::Sinatra::Extension }
11
+ @app.extend(CallWithMockRequestMixin)
12
+ @app.reset!
13
+ end
14
+
15
+ def test_basic
16
+ response = @app.call_with_mock_request('/bar')
17
+ assert_equal 404, response.status
18
+ end
19
+
20
+ def test_map_index
21
+ @app.get("/") { "index" }
22
+ response = @app.call_with_mock_request('/')
23
+ assert_equal 200, response.status
24
+ assert_equal "index", response.body
25
+ end
26
+
27
+ def test_trailing_slash
28
+ @app.get("/foo") { "foo" }
29
+ response = @app.call_with_mock_request('/foo')
30
+ assert_equal 200, response.status
31
+ assert_equal "foo", response.body
32
+ response = @app.call_with_mock_request('/foo/')
33
+ assert_equal 200, response.status
34
+ assert_equal "foo", response.body
35
+ end
36
+
37
+ def test_trailing_slash2
38
+ @app.get("/foo") { "foo" }
39
+ @app.get("/foo/bar") { "bar" }
40
+ response = @app.call_with_mock_request('/foo')
41
+ assert_equal 200, response.status
42
+ assert_equal "foo", response.body
43
+ response = @app.call_with_mock_request('/foo/bar')
44
+ assert_equal 200, response.status
45
+ assert_equal "bar", response.body
46
+ response = @app.call_with_mock_request('/foo/')
47
+ assert_equal 200, response.status
48
+ assert_equal "foo", response.body
49
+ response = @app.call_with_mock_request('/foo/bar/')
50
+ assert_equal 200, response.status
51
+ assert_equal "bar", response.body
52
+ end
53
+
54
+ def test_trailing_slash_with_optional_param
55
+ @app.get("/foo/(:bar)") { params[:bar] }
56
+ @app.get("/bar(/:foo)") { params[:foo] }
57
+ response = @app.call_with_mock_request('/foo/bar')
58
+ assert_equal 200, response.status
59
+ assert_equal "bar", response.body
60
+ response = @app.call_with_mock_request('/bar/foo')
61
+ assert_equal 200, response.status
62
+ assert_equal "foo", response.body
63
+ response = @app.call_with_mock_request('/bar')
64
+ assert_equal 200, response.status
65
+ assert_equal "", response.body
66
+ response = @app.call_with_mock_request('/bar/')
67
+ assert_equal 200, response.status
68
+ assert_equal "", response.body
69
+ end
70
+
71
+ def test_trailing_question_mark
72
+ @app.get("/foo/?") { "foo" }
73
+ response = @app.call_with_mock_request('/foo')
74
+ assert_equal 200, response.status
75
+ assert_equal "foo", response.body
76
+ response = @app.call_with_mock_request('/foo/')
77
+ assert_equal 200, response.status
78
+ assert_equal "foo", response.body
79
+ end
80
+
81
+ def test_map_basic
82
+ @app.get('/hi', :name => :hi) { generate(:hi) }
83
+ response = @app.call_with_mock_request('/hi')
84
+ assert_equal 200, response.status
85
+ assert_equal "/hi", response.body
86
+ end
87
+
88
+ def test_map_basic2
89
+ @app.get('/hi', :name => :hi) { generate(:hi) }
90
+ response = @app.call_with_mock_request('/hi/')
91
+ assert_equal 200, response.status
92
+ assert_equal "/hi", response.body
93
+ end
94
+
95
+ def test_map_param
96
+ @app.get('/hi/:id', :name => :hi) { generate(:hi, :id => 18) }
97
+ response = @app.call_with_mock_request('/hi/1')
98
+ assert_equal 200, response.status
99
+ assert_equal "/hi/18", response.body
100
+ end
101
+
102
+ def test_map_param2
103
+ @app.get('/hi-:id', :name => :hi) { generate(:hi, :id => 18) }
104
+ response = @app.call_with_mock_request('/hi-1')
105
+ assert_equal 200, response.status
106
+ assert_equal "/hi-18", response.body
107
+ end
108
+
109
+ def test_map_complex
110
+ @app.get('/hi/:foo/:bar/:baz(.:format)') { "/#{params[:foo]}/#{params[:bar]}/#{params[:baz]}/#{params[:format]}" }
111
+ response = @app.call_with_mock_request('/hi/foo/bar/baz')
112
+ assert_equal 200, response.status
113
+ assert_equal "/foo/bar/baz/", response.body
114
+ response = @app.call_with_mock_request('/hi/foo/bar-bax/baz')
115
+ assert_equal 200, response.status
116
+ assert_equal "/foo/bar-bax/baz/", response.body
117
+ end
118
+
119
+ def test_map_regexp
120
+ @app.get('/numbers/:digits', :matching => { :digits => /\d+/ }) { params[:digits] }
121
+ response = @app.call_with_mock_request('/numbers/2010')
122
+ assert_equal 200, response.status
123
+ assert_equal "2010", response.body
124
+ end
125
+
126
+ def test_not_map_regex
127
+ @app.get('/numbers/:digits', :matching => { :digits => /\d+/ }) { params[:digits] }
128
+ response = @app.call_with_mock_request('/numbers/nan')
129
+ assert_equal 404, response.status
130
+ end
131
+
132
+ def test_404
133
+ response = @app.call_with_mock_request('/bar')
134
+ assert_equal 404, response.status
135
+ assert_match response.body, /Sinatra doesn't know this ditty/
136
+ end
137
+
138
+ def test_405
139
+ @app.post('/bar') { 'foundpost' }
140
+ @app.put('/bar') { 'foundput' }
141
+ response = @app.call_with_mock_request('/bar')
142
+ assert_equal 405, response.status
143
+ assert_equal ['POST', 'PUT'], response.headers['Allow'].split(/\s*,\s*/).sort
144
+ end
145
+ end
metadata ADDED
@@ -0,0 +1,197 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: http_router_sinatra
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ version: 0.0.1
11
+ platform: ruby
12
+ authors:
13
+ - Joshua Hull
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-03-21 00:00:00 -07:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: http_router
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ hash: 3
30
+ segments:
31
+ - 0
32
+ - 6
33
+ - 2
34
+ version: 0.6.2
35
+ type: :runtime
36
+ version_requirements: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ name: sinatra
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ hash: 31
46
+ segments:
47
+ - 1
48
+ - 2
49
+ - 0
50
+ version: 1.2.0
51
+ type: :runtime
52
+ version_requirements: *id002
53
+ - !ruby/object:Gem::Dependency
54
+ name: minitest
55
+ prerelease: false
56
+ requirement: &id003 !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ hash: 15
62
+ segments:
63
+ - 2
64
+ - 0
65
+ - 0
66
+ version: 2.0.0
67
+ type: :development
68
+ version_requirements: *id003
69
+ - !ruby/object:Gem::Dependency
70
+ name: code_stats
71
+ prerelease: false
72
+ requirement: &id004 !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ hash: 3
78
+ segments:
79
+ - 0
80
+ version: "0"
81
+ type: :development
82
+ version_requirements: *id004
83
+ - !ruby/object:Gem::Dependency
84
+ name: rake
85
+ prerelease: false
86
+ requirement: &id005 !ruby/object:Gem::Requirement
87
+ none: false
88
+ requirements:
89
+ - - ">="
90
+ - !ruby/object:Gem::Version
91
+ hash: 3
92
+ segments:
93
+ - 0
94
+ version: "0"
95
+ type: :development
96
+ version_requirements: *id005
97
+ - !ruby/object:Gem::Dependency
98
+ name: rbench
99
+ prerelease: false
100
+ requirement: &id006 !ruby/object:Gem::Requirement
101
+ none: false
102
+ requirements:
103
+ - - ">="
104
+ - !ruby/object:Gem::Version
105
+ hash: 3
106
+ segments:
107
+ - 0
108
+ version: "0"
109
+ type: :development
110
+ version_requirements: *id006
111
+ - !ruby/object:Gem::Dependency
112
+ name: phocus
113
+ prerelease: false
114
+ requirement: &id007 !ruby/object:Gem::Requirement
115
+ none: false
116
+ requirements:
117
+ - - ">="
118
+ - !ruby/object:Gem::Version
119
+ hash: 3
120
+ segments:
121
+ - 0
122
+ version: "0"
123
+ type: :development
124
+ version_requirements: *id007
125
+ - !ruby/object:Gem::Dependency
126
+ name: bundler
127
+ prerelease: false
128
+ requirement: &id008 !ruby/object:Gem::Requirement
129
+ none: false
130
+ requirements:
131
+ - - ~>
132
+ - !ruby/object:Gem::Version
133
+ hash: 23
134
+ segments:
135
+ - 1
136
+ - 0
137
+ - 0
138
+ version: 1.0.0
139
+ type: :development
140
+ version_requirements: *id008
141
+ description: Kick ass router for Sinatra based on http_router.
142
+ email:
143
+ - joshbuddy@gmail.com
144
+ executables: []
145
+
146
+ extensions: []
147
+
148
+ extra_rdoc_files: []
149
+
150
+ files:
151
+ - .gitignore
152
+ - Gemfile
153
+ - Gemfile.lock
154
+ - README.md
155
+ - Rakefile
156
+ - http_router_sinatra.gemspec
157
+ - lib/http_router_sinatra.rb
158
+ - lib/http_router_sinatra/version.rb
159
+ - test/helper.rb
160
+ - test/test_recognize.rb
161
+ has_rdoc: true
162
+ homepage: https://github.com/joshbuddy/http_router_sinatra
163
+ licenses: []
164
+
165
+ post_install_message:
166
+ rdoc_options: []
167
+
168
+ require_paths:
169
+ - lib
170
+ required_ruby_version: !ruby/object:Gem::Requirement
171
+ none: false
172
+ requirements:
173
+ - - ">="
174
+ - !ruby/object:Gem::Version
175
+ hash: 3
176
+ segments:
177
+ - 0
178
+ version: "0"
179
+ required_rubygems_version: !ruby/object:Gem::Requirement
180
+ none: false
181
+ requirements:
182
+ - - ">="
183
+ - !ruby/object:Gem::Version
184
+ hash: 3
185
+ segments:
186
+ - 0
187
+ version: "0"
188
+ requirements: []
189
+
190
+ rubyforge_project: http_router_sinatra
191
+ rubygems_version: 1.3.7
192
+ signing_key:
193
+ specification_version: 3
194
+ summary: Kick ass router for Sinatra based on http_router
195
+ test_files:
196
+ - test/helper.rb
197
+ - test/test_recognize.rb