hobby 0.0.12 → 0.2.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 2d2d480ccdf4a60839072589bfaa58309a00bf4a
4
- data.tar.gz: e69b2439193e69c2f53adc780dac6666f71a01e6
2
+ SHA256:
3
+ metadata.gz: f7a734e16047e8e04ef87e68c1e20cb376dbaee578b756fb888244c6603d7c25
4
+ data.tar.gz: f0e946385562830eed6e1af944afe587ff3ae8957e7f1e268652a4223a2f89b5
5
5
  SHA512:
6
- metadata.gz: ff31f1f11344235dec85b8d021008a1b89a18ab65b8e4743add83b8e8e8e3104af567c8bdb01a5e84d6a78c5c9248a95272e3de7f3ac88fc6c60180a3e7266ee
7
- data.tar.gz: 723ba318c713c9d21c44c3bf8397e48a7204a562c7294545aedd7a26634a402887269878618cc61e91b3a2dcbe3454a0aa590dfde07f1cc51532c0d8123a0f2f
6
+ metadata.gz: c13de4d63efe75751e854d610e4cda08b658cd80f889b3e3d8e5e9b62d80f50ed2efa9dadcb91926b6669fb462ddf882d77fda11674d4b0c563debed8be1b0ed
7
+ data.tar.gz: 251399b7b9ca7340e843c6ce33c1dbf3ebe3a90ec50d62bba030e71a282c49e512c60a589e95613bd41d5c5b82b2adf9abe1adaa2f42d4f205cae8b45f4fe5f3
data/.travis.yml CHANGED
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  language: ruby
3
3
  rvm:
4
+ - 2.5
4
5
  - 2.4
5
6
  - 2.3
6
7
  script: bundle exec rspec
data/Gemfile CHANGED
@@ -1,7 +1,7 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- gem 'devtools', github: 'mbj/devtools'
4
- gem 'mutant', github: 'mbj/mutant'
3
+ gem 'devtools'
4
+ gem 'mutant'
5
5
  gem 'minitest'
6
6
  gem 'minitest-power_assert'
7
7
  gem 'rack-test'
data/hobby.gemspec CHANGED
@@ -4,10 +4,10 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
 
5
5
  Gem::Specification.new do |spec|
6
6
  spec.name = 'hobby'
7
- spec.version = '0.0.12'
7
+ spec.version = '0.2.0'
8
8
  spec.authors = ['Anatoly Chernow']
9
9
  spec.email = ['chertoly@gmail.com']
10
- spec.summary = %q{A minimal DSL over rack}
10
+ spec.summary = %q{A professional way to create Rack applications.}
11
11
  spec.homepage = 'https://github.com/ch1c0t/hobby'
12
12
  spec.license = 'MIT'
13
13
 
@@ -16,5 +16,7 @@ Gem::Specification.new do |spec|
16
16
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
17
17
  spec.require_paths = ['lib']
18
18
 
19
- spec.add_dependency 'rack'
19
+ spec.add_dependency 'rack', '>= 2'
20
+
21
+ spec.required_ruby_version = '>= 2.6.6'
20
22
  end
data/lib/hobby.rb CHANGED
@@ -10,20 +10,19 @@ module Hobby
10
10
 
11
11
  def self.included app
12
12
  app.extend Singleton
13
- app.builder, app.router = Rack::Builder.new, Router.new
13
+ app.router = Router.new
14
14
  app.request, app.response = Rack::Request, Rack::Response
15
15
  end
16
16
 
17
17
  module Singleton
18
- attr_accessor :builder, :router, :request, :response
18
+ attr_accessor :router, :request, :response
19
19
 
20
20
  def new (*)
21
- builder.run super
22
- builder.to_app
21
+ super.router.to_rack_app
23
22
  end
24
23
 
25
24
  extend Forwardable
26
- delegate [:map, :use] => :builder
25
+ delegate [:map, :use] => :router
27
26
 
28
27
  VERBS.each do |verb|
29
28
  define_method verb.downcase do |path = '/', &action|
@@ -41,9 +40,9 @@ module Hobby
41
40
  protected
42
41
  def handle env
43
42
  catch :halt do
44
- @route = self.class.router.route_for (@env = env)
43
+ @route = router.route_for (@env = env)
45
44
  fill_body
46
- response
45
+ response.to_a
47
46
  end
48
47
  end
49
48
 
data/lib/hobby/helpers.rb CHANGED
@@ -1,7 +1,19 @@
1
1
  module Hobby
2
2
  module Helpers
3
+ extend Forwardable
4
+
3
5
  attr_reader :env, :route
4
6
 
7
+ def router
8
+ @router ||= begin
9
+ router = self.class.router.clone
10
+ router.app = self
11
+ router
12
+ end
13
+ end
14
+
15
+ delegate [:map, :use] => :router
16
+
5
17
  def request
6
18
  @request ||= self.class.request.new env
7
19
  end
@@ -15,7 +27,7 @@ module Hobby
15
27
  end
16
28
 
17
29
  def halt
18
- throw :halt, response
30
+ throw :halt, response.to_a
19
31
  end
20
32
 
21
33
  def not_found
@@ -30,5 +42,9 @@ module Hobby
30
42
  def status status
31
43
  response.status = status
32
44
  end
45
+
46
+ def script_name
47
+ env.fetch 'SCRIPT_NAME'
48
+ end
33
49
  end
34
50
  end
data/lib/hobby/router.rb CHANGED
@@ -2,6 +2,11 @@ module Hobby
2
2
  class Router
3
3
  def initialize
4
4
  @routes = Routes.new
5
+ @uses, @maps = [], []
6
+ end
7
+
8
+ def initialize_copy _router
9
+ @uses, @maps = @uses.dup, @maps.dup
5
10
  end
6
11
 
7
12
  def add_route verb, path, &action
@@ -17,8 +22,33 @@ module Hobby
17
22
  route, params = @routes["#{env['REQUEST_METHOD']}#{env['PATH_INFO']}"]
18
23
  params ? route.with_params(params) : route
19
24
  end
25
+
26
+ def use *all
27
+ @uses << all
28
+ end
29
+
30
+ def map path, app = nil, &block
31
+ @maps << Builder::Map.new(path, app, &block)
32
+ end
33
+
34
+ attr_accessor :app
35
+
36
+ def to_rack_app
37
+ builder = create_builder
38
+ builder.run app
39
+ builder.to_app
40
+ end
41
+
42
+ private
43
+ def create_builder
44
+ builder = Builder.new
45
+ @uses.each { |all| builder.add_use *all }
46
+ @maps.each { |map| builder.add_map map }
47
+ builder
48
+ end
20
49
  end
21
50
  end
22
51
 
52
+ require 'hobby/router/builder'
23
53
  require 'hobby/router/routes'
24
54
  require 'hobby/router/route'
@@ -0,0 +1,25 @@
1
+ module Hobby
2
+ class Router
3
+ class Builder < Rack::Builder
4
+ # To work around
5
+ # https://github.com/mbj/mutant#the-crash--stuck-problem-mri
6
+ alias add_use use
7
+ alias add_map2 map
8
+
9
+ def add_map map
10
+ if map.app
11
+ add_map2 map.path do run map.app end
12
+ else
13
+ add_map2 map.path, &map.block
14
+ end
15
+ end
16
+
17
+ class Map
18
+ attr_reader :path, :app, :block
19
+ def initialize path, app, &block
20
+ @path, @app, @block = path, app, block
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
data/readme.adoc CHANGED
@@ -27,8 +27,16 @@ $ gem install hobby
27
27
  [[introduction]]
28
28
  == Introduction
29
29
 
30
- Hobby features a Sinatra-like DSL, but in contrast to Sinatra,
31
- Hobby applications behave like usual Ruby classes.
30
+ Hobby provides a Ruby DSL to create web applications. It is well suited both for standalone and inside-Rails use.
31
+
32
+ The DSL looks a lot like Sinatra, but Hobby applications are
33
+
34
+ * more reusable
35
+ * more reliable
36
+ +
37
+ The API and the codebase are much smaller and fully covered with specs. 100% mutation coverage is constantly maintained.
38
+ * https://github.com/luislavena/bench-micro#requestssec[more performant]
39
+ * https://github.com/luislavena/bench-micro#memory-allocationrequest[consume less resources]
32
40
 
33
41
  To create a Hobby application, you create a class and include `Hobby` in it.
34
42
  For example:
@@ -40,9 +48,9 @@ require 'hobby'
40
48
  class C
41
49
  include Hobby
42
50
 
43
- get("/hello") {
51
+ get "/hello" do
44
52
  "Hello, world."
45
- }
53
+ end
46
54
  end
47
55
  ----
48
56
 
@@ -74,9 +82,9 @@ class C
74
82
  @name = name
75
83
  end
76
84
 
77
- get("/hello") {
85
+ get "/hello" do
78
86
  "Hello, #{@name}."
79
- }
87
+ end
80
88
  end
81
89
  ----
82
90
 
@@ -95,9 +103,9 @@ class C
95
103
  @name.upcase
96
104
  end
97
105
 
98
- get("/hello") {
106
+ get "/hello" do
99
107
  "Hello, #{name}."
100
- }
108
+ end
101
109
  end
102
110
  ----
103
111
 
@@ -133,29 +141,12 @@ For common HTTP verbs, Hobby provides the route definers(methods named according
133
141
  class App
134
142
  include Hobby
135
143
 
136
- get '/' do
137
- # ...
138
- end
139
-
140
- post '/' do
141
- # ...
142
- end
143
-
144
- put '/' do
145
- # ...
146
- end
147
-
148
- patch '/' do
149
- # ...
150
- end
151
-
152
- delete '/' do
153
- # ...
154
- end
155
-
156
- options '/' do
157
- # ...
158
- end
144
+ get { 'Some string.' }
145
+ post { 'Some string.' }
146
+ put { 'Some string.' }
147
+ patch { 'Some string.' }
148
+ delete { 'Some string.' }
149
+ # TODO: find a good example for `options`
159
150
  end
160
151
  ----
161
152
 
@@ -285,8 +276,8 @@ to '/anatoly' and '/patricio' routes:
285
276
  class App
286
277
  include Hobby
287
278
 
288
- map('/anatoly') { run C.new 'Anatoly' }
289
- map('/patricio') { run C.new 'Patricio' }
279
+ map '/anatoly', C.new('Anatoly')
280
+ map '/patricio', C.new('Patricio')
290
281
 
291
282
  get '/' do
292
283
  'Mapping app.'
@@ -327,7 +318,6 @@ Many components of an application can be customized or replaced.
327
318
  class App
328
319
  include Hobby
329
320
 
330
- self.builder = custom_builder
331
321
  self.router = custom_router
332
322
  self.request = custom_request
333
323
  self.response = custom_response
@@ -350,5 +340,5 @@ To perform mutation analysis:
350
340
 
351
341
  [source,bash]
352
342
  ----
353
- bundle exec mutant --use rspec 'Hobby*'
343
+ bundle exec mutant --use rspec 'Hobby*' --include lib --require hobby
354
344
  ----
data/spec/app_spec.rb CHANGED
@@ -75,6 +75,17 @@ describe Hobby::App do
75
75
  end
76
76
  end
77
77
 
78
+ describe '#router' do
79
+ it 'gives a distinct router to each app' do
80
+ app = Class.new { include Hobby }
81
+
82
+ first_instance = app.new
83
+ second_instance = app.new
84
+
85
+ assert { not first_instance.router.equal? second_instance.router }
86
+ end
87
+ end
88
+
78
89
  describe :integration do
79
90
  before do
80
91
  described_class.app = build_app described_class
@@ -89,6 +100,51 @@ describe Hobby::App do
89
100
  get '/map'
90
101
  assert { last_response.body == 'from map' }
91
102
  end
103
+
104
+ it 'mounts an application to the rack stack with old deprecated syntax' do
105
+ get '/deprecated_map'
106
+ assert { last_response.body == 'from deprecated map' }
107
+ end
108
+ end
109
+
110
+ describe MapInsideInitialize do
111
+ describe 'without any passed arguments' do
112
+ def app
113
+ described_class.app.new
114
+ end
115
+
116
+ it do
117
+ get '/'
118
+ assert { last_response.body == 'hello world' }
119
+ get '/first_map'
120
+ assert { last_response.body == 'first mapapp' }
121
+ get '/second_map'
122
+ assert { last_response.body == 'second mapapp' }
123
+ end
124
+ end
125
+
126
+ describe 'with passed routes' do
127
+ def app
128
+ some_app = Class.new {
129
+ include Hobby
130
+ get { 'Some string.' }
131
+ }
132
+ routes = { '/third_map' => some_app.new }
133
+ described_class.app.new routes
134
+ end
135
+
136
+ it do
137
+ get '/'
138
+ assert { last_response.body == 'hello world' }
139
+ get '/first_map'
140
+ assert { last_response.body == 'first mapapp' }
141
+ get '/second_map'
142
+ assert { last_response.body == 'second mapapp' }
143
+
144
+ get '/third_map'
145
+ assert { last_response.body == 'Some string.' }
146
+ end
147
+ end
92
148
  end
93
149
 
94
150
  describe Use do
@@ -98,6 +154,13 @@ describe Hobby::App do
98
154
  end
99
155
  end
100
156
 
157
+ describe UseInsideInitialize do
158
+ it do
159
+ get '/'
160
+ assert { last_response.content_type == 'application/json' }
161
+ end
162
+ end
163
+
101
164
  describe WithoutPath do
102
165
  it 'is accessible as /' do
103
166
  get '/'
@@ -171,5 +234,53 @@ describe Hobby::App do
171
234
  assert { last_response.body == 'Created.' }
172
235
  end
173
236
  end
237
+
238
+ describe UnshareableRouterMaps do
239
+ it do
240
+ get '/1/first'
241
+ assert { last_response.body == 'The name is A.' }
242
+ get '/1/second'
243
+ assert { last_response.body == 'The name is B.' }
244
+ get '/1/third'
245
+ assert { last_response.body == '404' }
246
+
247
+ get '/2/first'
248
+ assert { last_response.body == 'The name is A.' }
249
+ get '/2/second'
250
+ assert { last_response.body == 'The name is B.' }
251
+ get '/2/third'
252
+ assert { last_response.body == 'The name is C.' }
253
+
254
+ get '/3/first'
255
+ assert { last_response.body == 'The name is A.' }
256
+ get '/3/second'
257
+ assert { last_response.body == 'The name is B.' }
258
+ get '/3/third'
259
+ assert { last_response.body == '404' }
260
+ end
261
+ end
262
+
263
+ describe UnshareableRouterUses do
264
+ it do
265
+ get '/1'
266
+ assert { last_response.content_type == 'application/html' }
267
+
268
+ get '/2'
269
+ assert { last_response.content_type == 'application/json' }
270
+
271
+ get '/3'
272
+ assert { last_response.content_type == 'application/html' }
273
+ end
274
+ end
275
+
276
+ describe ScriptName do
277
+ it do
278
+ get '/'
279
+ assert { last_response.body == '' }
280
+
281
+ get '/some/path'
282
+ assert { last_response.body == '/some/path' }
283
+ end
284
+ end
174
285
  end
175
286
  end
data/spec/apps/Map.rb CHANGED
@@ -1,5 +1,5 @@
1
- map '/map' do
2
- run Proc.new { |env| [200, {}, ['from map']] }
1
+ map '/map', Proc.new { |env| [200, {}, ['from map']] }
2
+ map '/deprecated_map' do
3
+ run Proc.new { |env| [200, {}, ['from deprecated map']] }
3
4
  end
4
-
5
5
  get('/') { 'hello world' }
@@ -0,0 +1,13 @@
1
+ first_app = Proc.new { |env| [200, {}, ['first mapapp']] }
2
+ second_app = Proc.new { |env| [200, {}, ['second mapapp']] }
3
+
4
+ map '/first_map', first_app
5
+ map '/second_map', second_app
6
+
7
+ get('/') { 'hello world' }
8
+
9
+ def initialize hash = {}
10
+ hash.each do |route, app|
11
+ map route, app
12
+ end
13
+ end
data/spec/apps/Nested.rb CHANGED
@@ -1,17 +1,15 @@
1
- map('/nested') do
2
- nested_app = Class.new do
3
- include Hobby::App
1
+ nested_app = Class.new do
2
+ include Hobby::App
4
3
 
5
- def initialize first, second
6
- @a = first
7
- @b = second
8
- @c = yield
9
- end
10
-
11
- get do
12
- "#{@a}:#{@b}:#{@c}"
13
- end
4
+ def initialize first, second
5
+ @a = first
6
+ @b = second
7
+ @c = yield
14
8
  end
15
9
 
16
- run nested_app.new(:a, :b) { :c }
10
+ get do
11
+ "#{@a}:#{@b}:#{@c}"
12
+ end
17
13
  end
14
+
15
+ map '/nested', nested_app.new(:a, :b) { :c }
@@ -5,4 +5,12 @@ self.router = Class.new {
5
5
  def route_for _request
6
6
  -> { 'for any route' }
7
7
  end
8
+
9
+ attr_accessor :app
10
+
11
+ def to_rack_app
12
+ builder = Rack::Builder.new
13
+ builder.run app
14
+ builder.to_app
15
+ end
8
16
  }.new
@@ -0,0 +1,12 @@
1
+ get do
2
+ script_name
3
+ end
4
+
5
+ app = Class.new do
6
+ include Hobby
7
+ get do
8
+ script_name
9
+ end
10
+ end
11
+
12
+ map '/some/path', app.new
@@ -0,0 +1,29 @@
1
+ mapped_app = Class.new do
2
+ include Hobby
3
+
4
+ def initialize name
5
+ @name = name
6
+ end
7
+
8
+ get { "The name is #{@name}." }
9
+ end
10
+
11
+ mapping_app = Class.new do
12
+ include Hobby
13
+
14
+ map '/first', mapped_app.new('A')
15
+ map '/second', mapped_app.new('B')
16
+
17
+ def initialize routes = {}
18
+ routes.each do |route, app|
19
+ map route, app
20
+ end
21
+ end
22
+ end
23
+
24
+ map '/1', mapping_app.new
25
+
26
+ routes = { '/third' => mapped_app.new('C') }
27
+ map '/2', mapping_app.new(routes)
28
+
29
+ map '/3', mapping_app.new
@@ -0,0 +1,16 @@
1
+ require 'json'
2
+
3
+ app = Class.new do
4
+ include Hobby
5
+ get { 'hello world'.to_json }
6
+
7
+ use Rack::ContentType, 'application/html'
8
+
9
+ def initialize middleware_with_arguments = nil
10
+ use *middleware_with_arguments if middleware_with_arguments
11
+ end
12
+ end
13
+
14
+ map '/1', app.new
15
+ map '/2', app.new([Rack::ContentType, 'application/json'])
16
+ map '/3', app.new
@@ -0,0 +1,7 @@
1
+ require 'json'
2
+
3
+ get { 'hello world'.to_json }
4
+
5
+ def initialize
6
+ use Rack::ContentType, 'application/json'
7
+ end
data/spec/helper.rb CHANGED
@@ -1,19 +1,19 @@
1
1
  require 'devtools/spec_helper'
2
2
 
3
3
  require 'hobby'
4
+ require_relative 'mutant_patches' if defined? Mutant
4
5
 
5
6
  require 'minitest'
6
7
  require 'minitest-power_assert'
7
8
  Minitest::Assertions.prepend Minitest::PowerAssert::Assertions
8
9
 
9
- if defined? Mutant
10
- class Mutant::Selector::Expression
11
- def call _subject
12
- integration.all_tests
13
- end
10
+ module EnvFor
11
+ def env_for path, verb = 'GET'
12
+ {'REQUEST_METHOD' => verb, 'PATH_INFO' => path }
14
13
  end
15
14
  end
16
15
 
17
16
  RSpec.configure do |config|
18
17
  config.expect_with :rspec, :minitest
18
+ config.include EnvFor
19
19
  end
@@ -0,0 +1,27 @@
1
+ # Run all the specs for any subject.
2
+ class Mutant::Selector::Expression
3
+ def call _subject
4
+ integration.all_tests
5
+ end
6
+ end
7
+
8
+ # Do not silence stdout and stderr of the running mutation.
9
+ class Mutant::Isolation::Fork
10
+ def result
11
+ yield
12
+ end
13
+ end
14
+
15
+ # Print the source of the current mutation.
16
+ class Mutant::Loader
17
+ def call
18
+ source = Unparser.unparse node
19
+
20
+ puts <<~S
21
+ Current mutation:
22
+ #{source}
23
+ S
24
+
25
+ kernel.eval source, binding, subject.source_path.to_s, subject.source_line
26
+ end
27
+ end
@@ -2,10 +2,6 @@ module RouterMatchers
2
2
  extend self
3
3
  SOME_ROUTE = ->{:some_route}
4
4
 
5
- def env_for path, verb = 'GET'
6
- {'REQUEST_METHOD' => verb, 'PATH_INFO' => path }
7
- end
8
-
9
5
  def add_routes *routes
10
6
  routes.each { |route| subject.add_route 'GET', route, &SOME_ROUTE }
11
7
  end
@@ -22,7 +18,7 @@ module RouterMatchers
22
18
  route && (route.to_proc.call == SOME_ROUTE.call) && params_are_ok
23
19
  end
24
20
 
25
- chain :and_set_params do |**params|
21
+ chain :and_set_params do |params|
26
22
  @params = params
27
23
  end
28
24
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hobby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.12
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Anatoly Chernow
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-07-23 00:00:00.000000000 Z
11
+ date: 2021-03-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '0'
19
+ version: '2'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: '0'
26
+ version: '2'
27
27
  description:
28
28
  email:
29
29
  - chertoly@gmail.com
@@ -39,6 +39,7 @@ files:
39
39
  - lib/hobby.rb
40
40
  - lib/hobby/helpers.rb
41
41
  - lib/hobby/router.rb
42
+ - lib/hobby/router/builder.rb
42
43
  - lib/hobby/router/route.rb
43
44
  - lib/hobby/router/routes.rb
44
45
  - readme.adoc
@@ -49,12 +50,18 @@ files:
49
50
  - spec/apps/Halting.rb
50
51
  - spec/apps/Main.rb
51
52
  - spec/apps/Map.rb
53
+ - spec/apps/MapInsideInitialize.rb
52
54
  - spec/apps/Nested.rb
53
55
  - spec/apps/OneRouteRouter.rb
56
+ - spec/apps/ScriptName.rb
54
57
  - spec/apps/Status.rb
58
+ - spec/apps/UnshareableRouterMaps.rb
59
+ - spec/apps/UnshareableRouterUses.rb
55
60
  - spec/apps/Use.rb
61
+ - spec/apps/UseInsideInitialize.rb
56
62
  - spec/apps/WithoutPath.rb
57
63
  - spec/helper.rb
64
+ - spec/mutant_patches.rb
58
65
  - spec/router_matchers.rb
59
66
  - spec/router_spec.rb
60
67
  homepage: https://github.com/ch1c0t/hobby
@@ -69,18 +76,17 @@ required_ruby_version: !ruby/object:Gem::Requirement
69
76
  requirements:
70
77
  - - ">="
71
78
  - !ruby/object:Gem::Version
72
- version: '0'
79
+ version: 2.6.6
73
80
  required_rubygems_version: !ruby/object:Gem::Requirement
74
81
  requirements:
75
82
  - - ">="
76
83
  - !ruby/object:Gem::Version
77
84
  version: '0'
78
85
  requirements: []
79
- rubyforge_project:
80
- rubygems_version: 2.6.11
86
+ rubygems_version: 3.2.3
81
87
  signing_key:
82
88
  specification_version: 4
83
- summary: A minimal DSL over rack
89
+ summary: A professional way to create Rack applications.
84
90
  test_files:
85
91
  - spec/app_spec.rb
86
92
  - spec/apps/ContentType.rb
@@ -89,11 +95,17 @@ test_files:
89
95
  - spec/apps/Halting.rb
90
96
  - spec/apps/Main.rb
91
97
  - spec/apps/Map.rb
98
+ - spec/apps/MapInsideInitialize.rb
92
99
  - spec/apps/Nested.rb
93
100
  - spec/apps/OneRouteRouter.rb
101
+ - spec/apps/ScriptName.rb
94
102
  - spec/apps/Status.rb
103
+ - spec/apps/UnshareableRouterMaps.rb
104
+ - spec/apps/UnshareableRouterUses.rb
95
105
  - spec/apps/Use.rb
106
+ - spec/apps/UseInsideInitialize.rb
96
107
  - spec/apps/WithoutPath.rb
97
108
  - spec/helper.rb
109
+ - spec/mutant_patches.rb
98
110
  - spec/router_matchers.rb
99
111
  - spec/router_spec.rb