scorched 0.22 → 0.23
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGES.md +8 -4
- data/Gemfile +1 -1
- data/LICENSE +0 -0
- data/TODO.md +1 -1
- data/examples/restful_controller.ru +51 -0
- data/examples/simple.ru +3 -3
- data/lib/scorched.rb +2 -1
- data/lib/scorched/controller.rb +66 -61
- data/lib/scorched/dynamic_delegate.rb +0 -0
- data/lib/scorched/error.rb +0 -0
- data/lib/scorched/version.rb +2 -2
- data/scorched.gemspec +4 -3
- data/spec/controller_spec.rb +151 -154
- data/spec/options_spec.rb +0 -0
- data/spec/public/static.txt +0 -0
- data/spec/request_spec.rb +0 -0
- data/spec/views/composer.erb +0 -0
- data/spec/views/layout.erb +0 -0
- data/spec/views/main.erb +0 -0
- data/spec/views/other.str +0 -0
- data/spec/views/partial.erb +0 -0
- metadata +35 -21
- data/examples/rails_style_routing.ru +0 -48
File without changes
|
data/lib/scorched/error.rb
CHANGED
File without changes
|
data/lib/scorched/version.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
1
|
module Scorched
|
2
|
-
VERSION = '0.
|
3
|
-
end
|
2
|
+
VERSION = '0.23'
|
3
|
+
end
|
data/scorched.gemspec
CHANGED
@@ -15,9 +15,10 @@ Gem::Specification.new 'scorched', Scorched::VERSION do |s|
|
|
15
15
|
s.required_ruby_version = '>= 2.0.0'
|
16
16
|
|
17
17
|
s.add_dependency 'rack', '~> 1.4'
|
18
|
-
s.add_dependency 'rack-accept', '~> 0.4'
|
18
|
+
s.add_dependency 'rack-accept', '~> 0.4' # Used for Accept-Charset, Accept-Encoding and Accept-Language headers.
|
19
|
+
s.add_dependency 'scorched-accept', '~> 0.1' # Used for Accept header.
|
19
20
|
s.add_dependency 'tilt', '~> 1.4'
|
20
21
|
s.add_development_dependency 'rack-test', '~> 0.6'
|
21
22
|
s.add_development_dependency 'rspec', '~> 2.9'
|
22
|
-
s.add_development_dependency 'rake', '
|
23
|
-
end
|
23
|
+
s.add_development_dependency 'rake', '~> 10.4'
|
24
|
+
end
|
data/spec/controller_spec.rb
CHANGED
@@ -5,30 +5,30 @@ module Scorched
|
|
5
5
|
let(:generic_handler) do
|
6
6
|
proc { |env| [200, {}, ['ok']] }
|
7
7
|
end
|
8
|
-
|
8
|
+
|
9
9
|
it "contains a default set of configuration options" do
|
10
10
|
app.config.should be_a(Options)
|
11
11
|
app.config.length.should > 0
|
12
12
|
end
|
13
|
-
|
13
|
+
|
14
14
|
it "contains a set of default conditions" do
|
15
15
|
app.conditions.should be_a(Options)
|
16
16
|
app.conditions.length.should > 0
|
17
17
|
app.conditions[:method].should be_a(Proc)
|
18
18
|
end
|
19
|
-
|
19
|
+
|
20
20
|
describe "basic route handling" do
|
21
21
|
it "gracefully handles 404 errors" do
|
22
22
|
response = rt.get '/'
|
23
23
|
response.status.should == 404
|
24
24
|
end
|
25
|
-
|
25
|
+
|
26
26
|
it "handles a root rack call correctly" do
|
27
27
|
app << {pattern: '/$', target: generic_handler}
|
28
28
|
response = rt.get '/'
|
29
29
|
response.status.should == 200
|
30
30
|
end
|
31
|
-
|
31
|
+
|
32
32
|
it "does not maintain state between requests" do
|
33
33
|
app << {pattern: '/state', target: proc { |env| [200, {}, [@state = 1 + @state.to_i]] }}
|
34
34
|
response = rt.get '/state'
|
@@ -36,7 +36,7 @@ module Scorched
|
|
36
36
|
response = rt.get '/state'
|
37
37
|
response.body.should == '1'
|
38
38
|
end
|
39
|
-
|
39
|
+
|
40
40
|
it "raises exception when invalid mapping hash given" do
|
41
41
|
expect {
|
42
42
|
app << {pattern: '/'}
|
@@ -46,14 +46,14 @@ module Scorched
|
|
46
46
|
}.to raise_error(ArgumentError)
|
47
47
|
end
|
48
48
|
end
|
49
|
-
|
49
|
+
|
50
50
|
describe "URL matching" do
|
51
51
|
it 'always matches from the beginning of the URL' do
|
52
52
|
app << {pattern: 'about', target: generic_handler}
|
53
53
|
response = rt.get '/about'
|
54
54
|
response.status.should == 404
|
55
55
|
end
|
56
|
-
|
56
|
+
|
57
57
|
it "matches eagerly by default" do
|
58
58
|
req = nil
|
59
59
|
app << {pattern: '/*', target: proc do |env|
|
@@ -62,7 +62,7 @@ module Scorched
|
|
62
62
|
response = rt.get '/about'
|
63
63
|
req.captures.should == ['about']
|
64
64
|
end
|
65
|
-
|
65
|
+
|
66
66
|
it "can be forced to match end of URL" do
|
67
67
|
app << {pattern: '/about$', target: generic_handler}
|
68
68
|
response = rt.get '/about/us'
|
@@ -71,7 +71,7 @@ module Scorched
|
|
71
71
|
response = rt.get '/about/us'
|
72
72
|
response.status.should == 200
|
73
73
|
end
|
74
|
-
|
74
|
+
|
75
75
|
it "unescapes all characters except for the forward-slash and percent sign" do
|
76
76
|
app << {pattern: '/a (quite) big fish', target: generic_handler}
|
77
77
|
rt.get('/a%20%28quite%29%20big%20fish').status.should == 200
|
@@ -81,7 +81,7 @@ module Scorched
|
|
81
81
|
rt.get('/page%2Fabout').status.should == 200
|
82
82
|
rt.get('/page/about').status.should == 404
|
83
83
|
end
|
84
|
-
|
84
|
+
|
85
85
|
it "unmatched path doesn't always begin with a forward slash" do
|
86
86
|
gh = generic_handler
|
87
87
|
app << {pattern: '/ab', target: Class.new(Scorched::Controller) do
|
@@ -91,7 +91,7 @@ module Scorched
|
|
91
91
|
resp.status.should == 200
|
92
92
|
resp.body.should == "ok"
|
93
93
|
end
|
94
|
-
|
94
|
+
|
95
95
|
it "unmatched path begins with forward slash if last match was up to or included a forward slash" do
|
96
96
|
gh = generic_handler
|
97
97
|
app << {pattern: '/about/', target: Class.new(Scorched::Controller) do
|
@@ -103,7 +103,7 @@ module Scorched
|
|
103
103
|
rt.get('/about/us').body.should == "ok"
|
104
104
|
rt.get('/contact/us').body.should == "ok"
|
105
105
|
end
|
106
|
-
|
106
|
+
|
107
107
|
it "can match anonymous wildcards" do
|
108
108
|
req = nil
|
109
109
|
app << {pattern: '/anon/*/**', target: proc do |env|
|
@@ -112,7 +112,7 @@ module Scorched
|
|
112
112
|
response = rt.get '/anon/jeff/has/crabs'
|
113
113
|
req.captures.should == ['jeff', 'has/crabs']
|
114
114
|
end
|
115
|
-
|
115
|
+
|
116
116
|
it "can match named wildcards (ignoring anonymous captures)" do
|
117
117
|
req = nil
|
118
118
|
app << {pattern: '/anon/:name/*/::infliction', target: proc do |env|
|
@@ -121,7 +121,7 @@ module Scorched
|
|
121
121
|
response = rt.get '/anon/jeff/smith/has/crabs'
|
122
122
|
req.captures.should == {name: 'jeff', infliction: 'has/crabs'}
|
123
123
|
end
|
124
|
-
|
124
|
+
|
125
125
|
example "wildcards match one or more characters" do
|
126
126
|
app << {pattern: '/*', target: proc { |env| [200, {}, ['ok']] }}
|
127
127
|
rt.get('/').status.should == 404
|
@@ -139,7 +139,7 @@ module Scorched
|
|
139
139
|
rt.get('/').status.should == 404
|
140
140
|
rt.get('/dog/cat').status.should == 200
|
141
141
|
end
|
142
|
-
|
142
|
+
|
143
143
|
example "wildcards can optionally match zero or more characters" do
|
144
144
|
app << {pattern: '/*?', target: proc { |env| [200, {}, ['ok']] }}
|
145
145
|
rt.get('/').status.should == 200
|
@@ -157,7 +157,7 @@ module Scorched
|
|
157
157
|
rt.get('/').status.should == 200
|
158
158
|
rt.get('/dog/cat').status.should == 200
|
159
159
|
end
|
160
|
-
|
160
|
+
|
161
161
|
it "can match regex and preserve anonymous captures" do
|
162
162
|
req = nil
|
163
163
|
app << {pattern: %r{/anon/([^/]+)/(.+)}, target: proc do |env|
|
@@ -166,7 +166,7 @@ module Scorched
|
|
166
166
|
response = rt.get '/anon/jeff/has/crabs'
|
167
167
|
req.captures.should == ['jeff', 'has/crabs']
|
168
168
|
end
|
169
|
-
|
169
|
+
|
170
170
|
it "can match regex and preserve named captures (ignoring anonymous captures)" do
|
171
171
|
req = nil
|
172
172
|
app << {pattern: %r{/anon/(?<name>[^/]+)/([^/]+)/(?<infliction>.+)}, target: proc do |env|
|
@@ -175,7 +175,7 @@ module Scorched
|
|
175
175
|
response = rt.get '/anon/jeff/smith/has/crabs'
|
176
176
|
req.captures.should == {name: 'jeff', infliction: 'has/crabs'}
|
177
177
|
end
|
178
|
-
|
178
|
+
|
179
179
|
it "matches routes based on priority, otherwise giving precedence to those defined first" do
|
180
180
|
order = []
|
181
181
|
app << {pattern: '/', priority: -1, target: proc { |env| order << 'four'; [200, {}, ['ok']] }}
|
@@ -185,38 +185,35 @@ module Scorched
|
|
185
185
|
rt.get('/').body.should == 'ok'
|
186
186
|
order.should == %w{one two three four}
|
187
187
|
end
|
188
|
-
|
189
|
-
it "finds the best match for media type whilst respecting priority and definition order" do
|
190
|
-
app << {pattern: '/',
|
191
|
-
|
192
|
-
}}
|
193
|
-
app << {pattern: '/',
|
194
|
-
|
195
|
-
}}
|
196
|
-
app << {pattern: '/', priority: 1, target: proc { |env|
|
197
|
-
[200, {}, ['anything']]
|
198
|
-
}}
|
199
|
-
rt.get('/', media_type: 'application/json, */*;q=0.5').body.should == 'anything'
|
188
|
+
|
189
|
+
it "finds the best match for the media type whilst respecting priority and definition order" do
|
190
|
+
app << {pattern: '/', target: proc { |env| [200, {}, ['anything']] }}
|
191
|
+
app << {pattern: '/', conditions: {media_type: 'application/json'}, target: proc { |env| [200, {}, ['application/json']] }}
|
192
|
+
app << {pattern: '/', conditions: {media_type: 'text/html'}, target: proc { |env| [200, {}, ['text/html']] }}
|
193
|
+
app << {pattern: '/', priority: 1, target: proc { |env| [200, {}, ['anything_high_priority']] }}
|
194
|
+
rt.get('/', {}, 'HTTP_ACCEPT' => 'application/json, */*;q=0.5').body.should == 'anything_high_priority'
|
200
195
|
app.mappings.pop
|
201
|
-
rt.get('/', {}, 'HTTP_ACCEPT' => '
|
202
|
-
rt.get('/', {}, 'HTTP_ACCEPT' => '
|
196
|
+
rt.get('/', {}, 'HTTP_ACCEPT' => 'application/json;q=0.5, text/html').body.should == 'text/html'
|
197
|
+
rt.get('/', {}, 'HTTP_ACCEPT' => 'application/json, */*').body.should == 'application/json'
|
198
|
+
rt.get('/', {}, 'HTTP_ACCEPT' => '*/*, text/*').body.should == 'text/html'
|
199
|
+
rt.get('/', {}, 'HTTP_ACCEPT' => '*/*').body.should == 'anything'
|
203
200
|
end
|
204
201
|
end
|
205
|
-
|
202
|
+
|
206
203
|
describe "conditions" do
|
207
204
|
it "contains a default set of conditions" do
|
208
205
|
app.conditions.should be_a(Options)
|
209
206
|
app.conditions.should include(:method, :media_type)
|
210
207
|
app.conditions.each { |k,v| v.should be_a(Proc) }
|
211
208
|
end
|
212
|
-
|
209
|
+
|
213
210
|
it "executes route only if all conditions return true" do
|
214
211
|
app << {pattern: '/$', conditions: {method: 'POST'}, target: generic_handler}
|
215
212
|
response = rt.get "/"
|
216
213
|
response.status.should be_between(400, 499)
|
217
214
|
response = rt.post "/"
|
218
215
|
response.status.should == 200
|
219
|
-
|
216
|
+
|
220
217
|
app.conditions[:has_name] = proc { |name| request.GET['name'] }
|
221
218
|
app << {pattern: '/about', conditions: {method: ['GET', 'POST'], has_name: 'Ronald'}, target: generic_handler}
|
222
219
|
response = rt.get "/about"
|
@@ -224,28 +221,28 @@ module Scorched
|
|
224
221
|
response = rt.get "/about", name: 'Ronald'
|
225
222
|
response.status.should == 200
|
226
223
|
end
|
227
|
-
|
224
|
+
|
228
225
|
it "raises exception when condition doesn't exist or is invalid" do
|
229
226
|
app << {pattern: '/', conditions: {surprise_christmas_turkey: true}, target: generic_handler}
|
230
227
|
expect {
|
231
228
|
rt.get "/"
|
232
229
|
}.to raise_error(Scorched::Error)
|
233
230
|
end
|
234
|
-
|
231
|
+
|
235
232
|
it "falls through to next route when conditions are not met" do
|
236
233
|
app << {pattern: '/', conditions: {method: 'POST'}, target: proc { |env| [200, {}, ['post']] }}
|
237
234
|
app << {pattern: '/', conditions: {method: 'GET'}, target: proc { |env| [200, {}, ['get']] }}
|
238
235
|
rt.get("/").body.should == 'get'
|
239
236
|
rt.post("/").body.should == 'post'
|
240
237
|
end
|
241
|
-
|
238
|
+
|
242
239
|
it "inverts the conditions if it's referenced with a trailing exclamation mark" do
|
243
240
|
app << {pattern: '/', conditions: {method!: 'GET'}, target: proc { |env| [200, {}, ['ok']] }}
|
244
241
|
rt.get("/").status.should == 405
|
245
242
|
rt.post("/").status.should == 200
|
246
243
|
end
|
247
244
|
end
|
248
|
-
|
245
|
+
|
249
246
|
describe "route helpers" do
|
250
247
|
it "allows end points to be defined more succinctly" do
|
251
248
|
route_proc = app.route('/*', 2, method: 'GET') { |capture| capture }
|
@@ -253,7 +250,7 @@ module Scorched
|
|
253
250
|
mapping.should == {pattern: mapping[:pattern], priority: 2, conditions: {method: 'GET'}, target: route_proc}
|
254
251
|
rt.get('/about').body.should == 'about'
|
255
252
|
end
|
256
|
-
|
253
|
+
|
257
254
|
it "can provide a mapping proc without mapping it" do
|
258
255
|
block = proc { |capture| capture }
|
259
256
|
wrapped_block = app.route(&block)
|
@@ -262,32 +259,32 @@ module Scorched
|
|
262
259
|
app << {pattern: '/*', target: wrapped_block}
|
263
260
|
rt.get('/turkey').body.should == 'turkey'
|
264
261
|
end
|
265
|
-
|
262
|
+
|
266
263
|
it "provides a method for every HTTP method" do
|
267
264
|
[:get, :post, :put, :delete, :options, :head, :patch].each do |m|
|
268
265
|
app.send(m, '/say_cool') { 'cool' }
|
269
266
|
rt.send(m, '/say_cool').body.should == (m == :head ? '' : 'cool')
|
270
267
|
end
|
271
268
|
end
|
272
|
-
|
269
|
+
|
273
270
|
it "provides wildcard captures as arguments" do
|
274
271
|
app.get('/*/**') { |a,b| "#{a} #{b}" }
|
275
272
|
rt.get('/hello/there/dude').body.should == 'hello there/dude'
|
276
273
|
end
|
277
|
-
|
274
|
+
|
278
275
|
it "provides named captures as individual arguments for each value" do
|
279
276
|
app.get('/:given_name') { |a| a }
|
280
277
|
app.get('/:given_name/::surname') { |a,b| "#{a} #{b}" }
|
281
278
|
rt.get('/bob').body.should == 'bob'
|
282
279
|
rt.get('/bob/smith').body.should == 'bob smith'
|
283
280
|
end
|
284
|
-
|
281
|
+
|
285
282
|
it "always matches to the end of the URL (implied $)" do
|
286
283
|
app.get('/') { 'awesome '}
|
287
284
|
rt.get('/dog').status.should == 404
|
288
285
|
rt.get('/').status.should == 200
|
289
286
|
end
|
290
|
-
|
287
|
+
|
291
288
|
it "leaves body empty if nil is returned" do
|
292
289
|
app.get('/') { }
|
293
290
|
app.after do
|
@@ -295,7 +292,7 @@ module Scorched
|
|
295
292
|
end
|
296
293
|
rt.get('/')
|
297
294
|
end
|
298
|
-
|
295
|
+
|
299
296
|
it "can take an array of patterns" do
|
300
297
|
app.get(['/', '/dog']) { 'rad' }
|
301
298
|
rt.get('/dog').status.should == 200
|
@@ -303,7 +300,7 @@ module Scorched
|
|
303
300
|
rt.get('/cat').status.should == 404
|
304
301
|
end
|
305
302
|
end
|
306
|
-
|
303
|
+
|
307
304
|
describe "sub-controllers" do
|
308
305
|
it "should ignore the already matched portions of the path" do
|
309
306
|
app << {pattern: '/article', target: Class.new(Scorched::Controller) do
|
@@ -321,7 +318,7 @@ module Scorched
|
|
321
318
|
'hello'
|
322
319
|
end
|
323
320
|
end
|
324
|
-
|
321
|
+
|
325
322
|
resp = rt.get('/article/name')
|
326
323
|
resp.status.should == 200
|
327
324
|
outer_env['SCRIPT_NAME'].should == ''
|
@@ -329,7 +326,7 @@ module Scorched
|
|
329
326
|
inner_env['SCRIPT_NAME'].should == '/article'
|
330
327
|
inner_env['PATH_INFO'].should == '/name'
|
331
328
|
end
|
332
|
-
|
329
|
+
|
333
330
|
example "PATH_INFO and SCRIPT_NAME joined, should produce a full path" do
|
334
331
|
app.controller '/article/' do
|
335
332
|
get '/name' do
|
@@ -354,7 +351,7 @@ module Scorched
|
|
354
351
|
response.status.should == 200
|
355
352
|
response.body.should == 'hello'
|
356
353
|
end
|
357
|
-
|
354
|
+
|
358
355
|
it "can be given a pattern" do
|
359
356
|
app.controller '/dog' do
|
360
357
|
get('/') { 'roof' }
|
@@ -363,12 +360,12 @@ module Scorched
|
|
363
360
|
response.status.should == 200
|
364
361
|
response.body.should == 'roof'
|
365
362
|
end
|
366
|
-
|
363
|
+
|
367
364
|
it "inherits from parent class, or otherwise the specified class" do
|
368
365
|
app.controller{}.superclass.should == app
|
369
366
|
app.controller('/', String){}.superclass.should == String
|
370
367
|
end
|
371
|
-
|
368
|
+
|
372
369
|
it "can take mapping options" do
|
373
370
|
app.controller priority: -1, conditions: {method: 'POST'} do
|
374
371
|
route('/') { 'ok' }
|
@@ -377,7 +374,7 @@ module Scorched
|
|
377
374
|
rt.get('/').status.should be_between(400, 499)
|
378
375
|
rt.post('/').body.should == 'ok'
|
379
376
|
end
|
380
|
-
|
377
|
+
|
381
378
|
it "automatically passes to the outer controller when no match" do
|
382
379
|
filters_run = 0
|
383
380
|
app.controller do
|
@@ -389,7 +386,7 @@ module Scorched
|
|
389
386
|
rt.get('/').body.should == 'hello'
|
390
387
|
filters_run.should == 0
|
391
388
|
end
|
392
|
-
|
389
|
+
|
393
390
|
it "can be used to map a predefined controller" do
|
394
391
|
person_controller = Class.new(Scorched::Controller) do
|
395
392
|
get('/name') { 'George' }
|
@@ -399,7 +396,7 @@ module Scorched
|
|
399
396
|
end
|
400
397
|
end
|
401
398
|
end
|
402
|
-
|
399
|
+
|
403
400
|
describe "before/after filters" do
|
404
401
|
they "run directly before and after the target action" do
|
405
402
|
order = []
|
@@ -409,7 +406,7 @@ module Scorched
|
|
409
406
|
rt.get('/')
|
410
407
|
order.should == [:before, :action, :after]
|
411
408
|
end
|
412
|
-
|
409
|
+
|
413
410
|
they "run in the context of the controller (same as the route)" do
|
414
411
|
route_instance = nil
|
415
412
|
before_instance = nil
|
@@ -421,7 +418,7 @@ module Scorched
|
|
421
418
|
route_instance.should == before_instance
|
422
419
|
route_instance.should == after_instance
|
423
420
|
end
|
424
|
-
|
421
|
+
|
425
422
|
they "should run even if no route matches" do
|
426
423
|
counter = 0
|
427
424
|
app.before { counter += 1 }
|
@@ -429,7 +426,7 @@ module Scorched
|
|
429
426
|
rt.delete('/').status.should == 404
|
430
427
|
counter.should == 2
|
431
428
|
end
|
432
|
-
|
429
|
+
|
433
430
|
they "can take an optional set of conditions" do
|
434
431
|
counter = 0
|
435
432
|
app.before(method: ['GET', 'PUT']) { counter += 1 }
|
@@ -439,7 +436,7 @@ module Scorched
|
|
439
436
|
rt.put('/')
|
440
437
|
counter.should == 4
|
441
438
|
end
|
442
|
-
|
439
|
+
|
443
440
|
they "execute in the order they're defined" do
|
444
441
|
order = []
|
445
442
|
app.before { order << :first }
|
@@ -449,7 +446,7 @@ module Scorched
|
|
449
446
|
rt.get('/')
|
450
447
|
order.should == %i{first second third fourth}
|
451
448
|
end
|
452
|
-
|
449
|
+
|
453
450
|
describe "nesting" do
|
454
451
|
example "filters inherit but only run once" do
|
455
452
|
before_counter, after_counter = 0, 0
|
@@ -458,18 +455,18 @@ module Scorched
|
|
458
455
|
subcontroller = app.controller { get('/') { 'wow' } }
|
459
456
|
subcontroller.filters[:before].should == app.filters[:before]
|
460
457
|
subcontroller.filters[:after].should == app.filters[:after]
|
461
|
-
|
458
|
+
|
462
459
|
rt.get('/')
|
463
460
|
before_counter.should == 1
|
464
461
|
after_counter.should == 1
|
465
|
-
|
462
|
+
|
466
463
|
# Hitting the subcontroller directly should yield the same results.
|
467
464
|
before_counter, after_counter = 0, 0
|
468
465
|
Rack::Test::Session.new(subcontroller).get('/')
|
469
466
|
before_counter.should == 1
|
470
467
|
after_counter.should == 1
|
471
468
|
end
|
472
|
-
|
469
|
+
|
473
470
|
example "before filters run from outermost to innermost" do
|
474
471
|
order = []
|
475
472
|
app.before { order << :outer }
|
@@ -482,7 +479,7 @@ module Scorched
|
|
482
479
|
rt.get('/')
|
483
480
|
order.should == %i{outer outer2 inner inner2}
|
484
481
|
end
|
485
|
-
|
482
|
+
|
486
483
|
example "after filters run from innermost to outermost" do
|
487
484
|
order = []
|
488
485
|
app.after { order << :outer }
|
@@ -495,7 +492,7 @@ module Scorched
|
|
495
492
|
rt.get('/')
|
496
493
|
order.should == %i{inner inner2 outer outer2}
|
497
494
|
end
|
498
|
-
|
495
|
+
|
499
496
|
example "inherited filters which fail to satisfy their conditions are re-evaluated at every level" do
|
500
497
|
order = []
|
501
498
|
sub_class = app.controller do
|
@@ -518,7 +515,7 @@ module Scorched
|
|
518
515
|
end
|
519
516
|
end
|
520
517
|
end
|
521
|
-
|
518
|
+
|
522
519
|
describe "error filters" do
|
523
520
|
let(:app) do
|
524
521
|
Class.new(Scorched::Controller) do
|
@@ -527,26 +524,26 @@ module Scorched
|
|
527
524
|
end
|
528
525
|
end
|
529
526
|
end
|
530
|
-
|
527
|
+
|
531
528
|
they "catch exceptions" do
|
532
529
|
app.error { response.status = 500 }
|
533
530
|
rt.get('/').status.should == 500
|
534
531
|
end
|
535
|
-
|
532
|
+
|
536
533
|
they "receive the exception object as their first argument" do
|
537
534
|
error = nil
|
538
535
|
app.error { |e| error = e }
|
539
536
|
rt.get('/')
|
540
537
|
error.should be_a(StandardError)
|
541
538
|
end
|
542
|
-
|
539
|
+
|
543
540
|
they "try the next handler if the previous handler returns false" do
|
544
541
|
handlers_called = 0
|
545
542
|
app.error { handlers_called += 1 }
|
546
543
|
app.error { handlers_called += 1 }
|
547
544
|
rt.get '/'
|
548
545
|
handlers_called.should == 1
|
549
|
-
|
546
|
+
|
550
547
|
app.error_filters.clear
|
551
548
|
handlers_called = 0
|
552
549
|
app.error { handlers_called += 1; false }
|
@@ -554,45 +551,45 @@ module Scorched
|
|
554
551
|
rt.get '/'
|
555
552
|
handlers_called.should == 2
|
556
553
|
end
|
557
|
-
|
554
|
+
|
558
555
|
they "still runs after filters if route error is handled" do
|
559
556
|
app.after { response.status = 111 }
|
560
557
|
app.error { true }
|
561
558
|
rt.get('/').status.should == 111
|
562
559
|
end
|
563
|
-
|
560
|
+
|
564
561
|
they "can handle exceptions in before/after filters" do
|
565
562
|
app.error { |e| response.write e.class.name }
|
566
563
|
app.after { raise ArgumentError }
|
567
564
|
rt.get('/').body.should == 'StandardErrorArgumentError'
|
568
565
|
end
|
569
|
-
|
566
|
+
|
570
567
|
they "swallow halts when executed in an outer context" do
|
571
568
|
app.before { raise "Big bad error" }
|
572
569
|
app.error { throw :halt }
|
573
570
|
rt.get('/') # Would otherwise bomb out with uncaught throw.
|
574
571
|
end
|
575
|
-
|
572
|
+
|
576
573
|
they "only get called once per error" do
|
577
574
|
times_called = 0
|
578
575
|
app.error { times_called += 1 }
|
579
576
|
rt.get '/'
|
580
577
|
times_called.should == 1
|
581
578
|
end
|
582
|
-
|
579
|
+
|
583
580
|
they "fall through when unhandled" do
|
584
581
|
expect {
|
585
582
|
rt.get '/'
|
586
583
|
}.to raise_error(StandardError)
|
587
584
|
end
|
588
|
-
|
585
|
+
|
589
586
|
they "can optionally filter on one or more exception types" do
|
590
587
|
app.get('/arg_error') { raise ArgumentError }
|
591
|
-
|
588
|
+
|
592
589
|
app.error(StandardError, ArgumentError) { true }
|
593
590
|
rt.get '/'
|
594
591
|
rt.get '/arg_error'
|
595
|
-
|
592
|
+
|
596
593
|
app.error_filters.clear
|
597
594
|
app.error(ArgumentError) { true }
|
598
595
|
expect {
|
@@ -600,7 +597,7 @@ module Scorched
|
|
600
597
|
}.to raise_error(StandardError)
|
601
598
|
rt.get '/arg_error'
|
602
599
|
end
|
603
|
-
|
600
|
+
|
604
601
|
they "can take an optional set of conditions" do
|
605
602
|
app.error(method: ['GET', 'PUT']) { true }
|
606
603
|
expect {
|
@@ -610,7 +607,7 @@ module Scorched
|
|
610
607
|
rt.put('/')
|
611
608
|
end
|
612
609
|
end
|
613
|
-
|
610
|
+
|
614
611
|
describe "middleware" do
|
615
612
|
let(:app) do
|
616
613
|
Class.new(Scorched::Controller) do
|
@@ -625,56 +622,56 @@ module Scorched
|
|
625
622
|
end
|
626
623
|
end
|
627
624
|
end
|
628
|
-
|
625
|
+
|
629
626
|
it "is only included once by default" do
|
630
627
|
rt.get('/').body.should == '1'
|
631
628
|
rt.get('/sub_controller').body.should == '1'
|
632
629
|
end
|
633
|
-
|
630
|
+
|
634
631
|
it "can be explicitly included more than once in sub-controllers" do
|
635
632
|
app.mappings[-1][:target].middleware << proc { use Scorched::SimpleCounter }
|
636
633
|
rt.get('/').body.should == '1'
|
637
634
|
rt.get('/sub_controller').body.should == '2'
|
638
635
|
end
|
639
636
|
end
|
640
|
-
|
637
|
+
|
641
638
|
describe "halting" do
|
642
639
|
it "short circuits current request" do
|
643
640
|
has_run = false
|
644
641
|
app.get('/') { halt; has_run = true }
|
645
642
|
rt.get '/'
|
646
|
-
has_run.should
|
643
|
+
has_run.should be_falsey
|
647
644
|
end
|
648
|
-
|
645
|
+
|
649
646
|
it "takes an optional status" do
|
650
647
|
app.get('/') { halt 600 }
|
651
648
|
rt.get('/').status.should == 600
|
652
649
|
end
|
653
|
-
|
650
|
+
|
654
651
|
it "takes an optional response body" do
|
655
652
|
app.get('/') { halt 'cool' }
|
656
653
|
rt.get('/').body.should == 'cool'
|
657
654
|
end
|
658
|
-
|
655
|
+
|
659
656
|
it "can take a status and a response body" do
|
660
657
|
app.get('/') { halt 600, 'cool' }
|
661
658
|
rt.get('/').status.should == 600
|
662
659
|
rt.get('/').body.should == 'cool'
|
663
660
|
end
|
664
|
-
|
661
|
+
|
665
662
|
it "still processes filters" do
|
666
663
|
app.after { response.status = 600 }
|
667
664
|
app.get('/') { halt }
|
668
665
|
rt.get('/').status.should == 600
|
669
666
|
end
|
670
|
-
|
667
|
+
|
671
668
|
describe "within filters" do
|
672
669
|
it "short circuits filters if halted within filter" do
|
673
670
|
app.before { halt }
|
674
671
|
app.after { response.status = 600 }
|
675
672
|
rt.get('/').status.should_not == 600
|
676
673
|
end
|
677
|
-
|
674
|
+
|
678
675
|
it "forced filters are always run" do
|
679
676
|
app.before { halt }
|
680
677
|
app.after(force: true) { response.status = 600 }
|
@@ -682,7 +679,7 @@ module Scorched
|
|
682
679
|
app.get('/') { 'hello' }
|
683
680
|
rt.get('/').status.should == 600
|
684
681
|
end
|
685
|
-
|
682
|
+
|
686
683
|
it "halting within a forced filter still runs other forced filters" do
|
687
684
|
app.before { halt }
|
688
685
|
app.before(force: true) { halt }
|
@@ -694,7 +691,7 @@ module Scorched
|
|
694
691
|
end
|
695
692
|
end
|
696
693
|
end
|
697
|
-
|
694
|
+
|
698
695
|
describe 'redirecting' do
|
699
696
|
it "redirects using 303 or 302 by default, depending on HTTP version" do
|
700
697
|
app.get('/cat') { redirect '/dog' }
|
@@ -705,12 +702,12 @@ module Scorched
|
|
705
702
|
response.status.should == 302
|
706
703
|
response.location.should == '/dog'
|
707
704
|
end
|
708
|
-
|
705
|
+
|
709
706
|
it "allows the HTTP status to be overridden" do
|
710
707
|
app.get('/') { redirect '/somewhere', 308 }
|
711
708
|
rt.get('/').status.should == 308
|
712
709
|
end
|
713
|
-
|
710
|
+
|
714
711
|
it "halts the request after redirect" do
|
715
712
|
var = false
|
716
713
|
app.get('/') do
|
@@ -720,7 +717,7 @@ module Scorched
|
|
720
717
|
rt.get('/')
|
721
718
|
var.should == false
|
722
719
|
end
|
723
|
-
|
720
|
+
|
724
721
|
it "works in filters" do
|
725
722
|
app.error { redirect '/somewhere' }
|
726
723
|
app.get('/') { raise "Some error" }
|
@@ -729,7 +726,7 @@ module Scorched
|
|
729
726
|
rt.get('/').location.should == '/somewhere_else'
|
730
727
|
end
|
731
728
|
end
|
732
|
-
|
729
|
+
|
733
730
|
describe "passing" do
|
734
731
|
it "invokes the next match" do
|
735
732
|
app.get('/') { response.body << 'hello'; pass }
|
@@ -738,7 +735,7 @@ module Scorched
|
|
738
735
|
app.get('/') { response.body << '!' } # Shouldn't be hit
|
739
736
|
rt.get('/').body.should == 'hello there sir'
|
740
737
|
end
|
741
|
-
|
738
|
+
|
742
739
|
it "invokes the next match in parent controller if passed from filter" do
|
743
740
|
effects = []
|
744
741
|
app.controller '/sub' do
|
@@ -756,7 +753,7 @@ module Scorched
|
|
756
753
|
rt.get('/sub').body.should == 'y'
|
757
754
|
effects.should == [1, 2]
|
758
755
|
end
|
759
|
-
|
756
|
+
|
760
757
|
it "results in uncaught symbol if passing within filter of root controller " do
|
761
758
|
app.before { pass }
|
762
759
|
expect {
|
@@ -764,36 +761,36 @@ module Scorched
|
|
764
761
|
rt.get('/')
|
765
762
|
}.to raise_error(ArgumentError)
|
766
763
|
end
|
767
|
-
|
764
|
+
|
768
765
|
it "is not considered a match if a mapping passes the request" do
|
769
766
|
app.get('/*') { pass }
|
770
767
|
app.get('/nopass') { }
|
771
768
|
handled = nil
|
772
769
|
app.after { handled = @_handled }
|
773
770
|
rt.get('/').status.should == 404 # 404 if matched, but passed
|
774
|
-
handled.
|
771
|
+
handled.should be_falsey
|
775
772
|
rt.get('/nopass').status.should == 200
|
776
|
-
handled.should
|
773
|
+
handled.should be_truthy
|
777
774
|
end
|
778
775
|
end
|
779
|
-
|
776
|
+
|
780
777
|
describe "status codes" do
|
781
778
|
it "returns 405 when :method condition fails" do
|
782
779
|
app.get('/') { }
|
783
780
|
rt.post('/').status.should == 405
|
784
781
|
end
|
785
|
-
|
782
|
+
|
786
783
|
it "returns 404 when :host condition fails" do
|
787
784
|
app.get('/', host: 'somehost') { }
|
788
785
|
rt.get('/').status.should == 404
|
789
786
|
end
|
790
|
-
|
787
|
+
|
791
788
|
it "returns 406 when accept-related conditions fail" do
|
792
789
|
app.get('/media_type', media_type: 'application/json') { }
|
793
790
|
app.get('/charset', charset: 'iso-8859-5') { }
|
794
791
|
app.get('/encoding', encoding: 'gzip') { }
|
795
792
|
app.get('/language', language: 'en') { }
|
796
|
-
|
793
|
+
|
797
794
|
rt.get('/media_type', {}, 'HTTP_ACCEPT' => 'application/json').status.should == 200
|
798
795
|
rt.get('/media_type', {}, 'HTTP_ACCEPT' => 'text/html').status.should == 406
|
799
796
|
rt.get('/charset', {}, 'HTTP_ACCEPT_CHARSET' => 'iso-8859-5').status.should == 200
|
@@ -804,7 +801,7 @@ module Scorched
|
|
804
801
|
rt.get('/language', {}, 'HTTP_ACCEPT_LANGUAGE' => 'da').status.should == 406
|
805
802
|
end
|
806
803
|
end
|
807
|
-
|
804
|
+
|
808
805
|
describe "configuration" do
|
809
806
|
describe :strip_trailing_slash do
|
810
807
|
it "can be set to strip trailing slash and redirect" do
|
@@ -814,7 +811,7 @@ module Scorched
|
|
814
811
|
response.status.should == 307
|
815
812
|
response['Location'].should == '/test'
|
816
813
|
end
|
817
|
-
|
814
|
+
|
818
815
|
it "can be set to ignore trailing slash while pattern matching" do
|
819
816
|
app.config[:strip_trailing_slash] = :ignore
|
820
817
|
hit = false
|
@@ -822,17 +819,17 @@ module Scorched
|
|
822
819
|
rt.get('/test/').status.should == 200
|
823
820
|
hit.should == true
|
824
821
|
end
|
825
|
-
|
822
|
+
|
826
823
|
it "can be set not do nothing with a trailing slash" do
|
827
824
|
app.config[:strip_trailing_slash] = false
|
828
825
|
app.get('/test') { }
|
829
826
|
rt.get('/test/').status.should == 404
|
830
|
-
|
827
|
+
|
831
828
|
app.get('/test/') { }
|
832
829
|
rt.get('/test/').status.should == 200
|
833
830
|
end
|
834
831
|
end
|
835
|
-
|
832
|
+
|
836
833
|
describe :static_dir do
|
837
834
|
it "can serve static file from the specific directory" do
|
838
835
|
app.config[:static_dir] = 'public'
|
@@ -840,23 +837,23 @@ module Scorched
|
|
840
837
|
response.status.should == 200
|
841
838
|
response.body.should == 'My static file!'
|
842
839
|
end
|
843
|
-
|
840
|
+
|
844
841
|
it "can be disabled" do
|
845
842
|
app.config[:static_dir] = false
|
846
843
|
response = rt.get('/static.txt')
|
847
844
|
response.status.should == 404
|
848
845
|
end
|
849
846
|
end
|
850
|
-
|
847
|
+
|
851
848
|
describe :show_exceptions do
|
852
849
|
it "shows debug-friendly error page for unhandled exceptions" do
|
853
850
|
app.config[:show_exceptions] = true
|
854
851
|
app.get('/') { raise RuntimeError, "Kablamo!" }
|
855
|
-
response = rt.get('/')
|
852
|
+
response = rt.get('/', {}, 'HTTP_ACCEPT' => 'text/html')
|
856
853
|
response.status.should == 500
|
857
854
|
response.body.should include('Rack::ShowExceptions')
|
858
855
|
end
|
859
|
-
|
856
|
+
|
860
857
|
it "can be disabled" do
|
861
858
|
app.config[:show_exceptions] = false
|
862
859
|
app.get('/') { raise RuntimeError, "Kablamo!" }
|
@@ -865,7 +862,7 @@ module Scorched
|
|
865
862
|
}.to raise_error(RuntimeError)
|
866
863
|
end
|
867
864
|
end
|
868
|
-
|
865
|
+
|
869
866
|
describe :show_http_error_pages do
|
870
867
|
it "shows HTTP error pages for errors 400 to 599" do
|
871
868
|
app.config[:show_http_error_pages] = true
|
@@ -875,7 +872,7 @@ module Scorched
|
|
875
872
|
rt.post('/').body.should include('405 Method Not Allowed')
|
876
873
|
rt.get('/unknown').body.should include('480 ')
|
877
874
|
end
|
878
|
-
|
875
|
+
|
879
876
|
it "can be disabled" do
|
880
877
|
app.config[:show_http_error_pages] = false
|
881
878
|
app.get('/') { response.status = 501; '' }
|
@@ -885,7 +882,7 @@ module Scorched
|
|
885
882
|
rt.post('/unknown').body.should_not include('408 ')
|
886
883
|
end
|
887
884
|
end
|
888
|
-
|
885
|
+
|
889
886
|
describe :auto_pass do
|
890
887
|
it "passes to the outer controller without running any filters, if no match" do
|
891
888
|
sub = Class.new(Scorched::Controller) do
|
@@ -900,22 +897,22 @@ module Scorched
|
|
900
897
|
rt.get('/').status.should == 200
|
901
898
|
rt.get('/hello').body.should == 'hello'
|
902
899
|
rt.get('/hello').status.should == 600
|
903
|
-
|
900
|
+
|
904
901
|
sub.config[:auto_pass] = false
|
905
902
|
rt.get('/').body.should == ''
|
906
903
|
rt.get('/').status.should == 600
|
907
904
|
end
|
908
905
|
end
|
909
|
-
|
906
|
+
|
910
907
|
describe :cache_templates do
|
911
908
|
before(:each) do
|
912
909
|
File.open('views/temp.str', 'w') { |f| f.write 'hello world' }
|
913
910
|
end
|
914
|
-
|
911
|
+
|
915
912
|
after(:all) {
|
916
913
|
File.unlink 'views/temp.str'
|
917
914
|
}
|
918
|
-
|
915
|
+
|
919
916
|
it "can cache templates" do
|
920
917
|
app.config[:cache_templates] = true
|
921
918
|
app.get('/') { render :'temp.str' }
|
@@ -923,7 +920,7 @@ module Scorched
|
|
923
920
|
File.open('views/temp.str', 'a') { |f| f.write '!!!' }
|
924
921
|
rt.get('/').body.should == 'hello world'
|
925
922
|
end
|
926
|
-
|
923
|
+
|
927
924
|
it "can be set not to cache templates" do
|
928
925
|
app.config[:cache_templates] = false
|
929
926
|
app.get('/') { render :'temp.str' }
|
@@ -933,7 +930,7 @@ module Scorched
|
|
933
930
|
end
|
934
931
|
end
|
935
932
|
end
|
936
|
-
|
933
|
+
|
937
934
|
describe "sessions" do
|
938
935
|
it "provides convenience method for accessing the Rack session" do
|
939
936
|
rack_session = nil
|
@@ -944,49 +941,49 @@ module Scorched
|
|
944
941
|
rt.get('/')
|
945
942
|
rack_session.should be_a(Rack::Session::Abstract::SessionHash)
|
946
943
|
end
|
947
|
-
|
944
|
+
|
948
945
|
describe "flash" do
|
949
946
|
before(:each) do
|
950
947
|
app.middleware << proc { use Rack::Session::Cookie, secret: 'test' }
|
951
948
|
end
|
952
|
-
|
949
|
+
|
953
950
|
it "keeps session variables that live for one page load" do
|
954
951
|
app.get('/set') { flash[:cat] = 'meow' }
|
955
952
|
app.get('/get') { flash[:cat] }
|
956
|
-
|
953
|
+
|
957
954
|
rt.get('/set')
|
958
955
|
rt.get('/get').body.should == 'meow'
|
959
956
|
rt.get('/get').body.should == ''
|
960
957
|
end
|
961
|
-
|
958
|
+
|
962
959
|
it "always reads from the original request flash" do
|
963
960
|
app.get('/') do
|
964
961
|
flash[:counter] = flash[:counter] ? flash[:counter] + 1 : 0
|
965
962
|
flash[:counter].to_s
|
966
963
|
end
|
967
|
-
|
964
|
+
|
968
965
|
rt.get('/').body.should == ''
|
969
966
|
rt.get('/').body.should == '0'
|
970
967
|
rt.get('/').body.should == '1'
|
971
968
|
end
|
972
|
-
|
969
|
+
|
973
970
|
it "can only remove flash variables if the flash object is accessed" do
|
974
971
|
app.get('/set') { flash[:cat] = 'meow' }
|
975
972
|
app.get('/get') { flash[:cat] }
|
976
973
|
app.get('/null') { }
|
977
|
-
|
974
|
+
|
978
975
|
rt.get('/set')
|
979
976
|
rt.get('/null')
|
980
977
|
rt.get('/get').body.should == 'meow'
|
981
978
|
rt.get('/get').body.should == ''
|
982
979
|
end
|
983
|
-
|
980
|
+
|
984
981
|
it "can keep multiple sets of flash session variables" do
|
985
982
|
app.get('/set_animal') { flash(:animals)[:cat] = 'meow' }
|
986
983
|
app.get('/get_animal') { flash(:animals)[:cat] }
|
987
984
|
app.get('/set_name') { flash(:names)[:jeff] = 'male' }
|
988
985
|
app.get('/get_name') { flash(:names)[:jeff] }
|
989
|
-
|
986
|
+
|
990
987
|
rt.get('/set_animal')
|
991
988
|
rt.get('/set_name')
|
992
989
|
rt.get('/get_animal').body.should == 'meow'
|
@@ -996,7 +993,7 @@ module Scorched
|
|
996
993
|
end
|
997
994
|
end
|
998
995
|
end
|
999
|
-
|
996
|
+
|
1000
997
|
describe "cookie helper" do
|
1001
998
|
it "sets, retrieves and deletes cookies" do
|
1002
999
|
app.get('/') { cookie :test }
|
@@ -1004,7 +1001,7 @@ module Scorched
|
|
1004
1001
|
app.post('/goodbye') { cookie :test, {value: 'goodbye', expires: Time.now() + 999999 } }
|
1005
1002
|
app.delete('/') { cookie :test, nil }
|
1006
1003
|
app.delete('/alt') { cookie :test, {value: nil} }
|
1007
|
-
|
1004
|
+
|
1008
1005
|
rt.get('/').body.should == ''
|
1009
1006
|
rt.post('/')
|
1010
1007
|
rt.get('/').body.should == 'hello'
|
@@ -1016,7 +1013,7 @@ module Scorched
|
|
1016
1013
|
rt.get('/').body.should == ''
|
1017
1014
|
end
|
1018
1015
|
end
|
1019
|
-
|
1016
|
+
|
1020
1017
|
describe "rendering" do
|
1021
1018
|
before(:each) do
|
1022
1019
|
app.render_defaults.each { |k,v| app.render_defaults[k] = nil }
|
@@ -1042,7 +1039,7 @@ module Scorched
|
|
1042
1039
|
end
|
1043
1040
|
rt.get('/')
|
1044
1041
|
end
|
1045
|
-
|
1042
|
+
|
1046
1043
|
it "properly respects absolute and relative file paths in respect to the view directory" do
|
1047
1044
|
app.get('/relative') do
|
1048
1045
|
render(:'../views/main.erb', dir: 'views')
|
@@ -1105,14 +1102,14 @@ module Scorched
|
|
1105
1102
|
end
|
1106
1103
|
rt.get('/').body.should == '({1 for none}{1 for none})'
|
1107
1104
|
end
|
1108
|
-
|
1105
|
+
|
1109
1106
|
it "can pass local variables through to view" do
|
1110
1107
|
app.get '/' do
|
1111
1108
|
render '<%= var %>', engine: 'erb', dir: 'views', locals: {var: 'hello sailor'}
|
1112
1109
|
end
|
1113
1110
|
rt.get('/').body.should == 'hello sailor'
|
1114
1111
|
end
|
1115
|
-
|
1112
|
+
|
1116
1113
|
it "provides a means for passing options directly to tilt" do
|
1117
1114
|
Tilt.register(Class.new(Tilt::ERBTemplate) do
|
1118
1115
|
def prepare
|
@@ -1120,13 +1117,13 @@ module Scorched
|
|
1120
1117
|
super
|
1121
1118
|
end
|
1122
1119
|
end, 'test')
|
1123
|
-
|
1120
|
+
|
1124
1121
|
app.get '/safe' do
|
1125
1122
|
render '<%= var %>', engine: 'test', dir: 'views', locals: {var: 'hello sailor'}
|
1126
1123
|
render '<%= var %>', engine: 'test', dir: 'views', locals: {var: 'hello sailor'}, tilt: {engine: Class.new}
|
1127
1124
|
end
|
1128
1125
|
rt.get('/safe').body.should == 'hello sailor'
|
1129
|
-
|
1126
|
+
|
1130
1127
|
app.get '/boomer' do
|
1131
1128
|
render '<%= var %>', engine: 'test', dir: 'views', locals: {var: 'hello sailor'}, tilt: {engine: 'invalid'}
|
1132
1129
|
end
|
@@ -1135,12 +1132,12 @@ module Scorched
|
|
1135
1132
|
}.to raise_error(NoMethodError)
|
1136
1133
|
end
|
1137
1134
|
end
|
1138
|
-
|
1135
|
+
|
1139
1136
|
describe "url helpers" do
|
1140
1137
|
let(:my_app) do
|
1141
1138
|
Class.new(Scorched::Controller)
|
1142
1139
|
end
|
1143
|
-
|
1140
|
+
|
1144
1141
|
let(:root_app) do
|
1145
1142
|
Class.new(Scorched::Controller)
|
1146
1143
|
end
|
@@ -1152,7 +1149,7 @@ module Scorched
|
|
1152
1149
|
builder.map('/') { run this.root_app }
|
1153
1150
|
builder.to_app
|
1154
1151
|
end
|
1155
|
-
|
1152
|
+
|
1156
1153
|
it "can determine the root path of the current Scorched application" do
|
1157
1154
|
my_app.controller '/article' do
|
1158
1155
|
get '/name' do
|
@@ -1161,26 +1158,26 @@ module Scorched
|
|
1161
1158
|
end
|
1162
1159
|
rt.get('/myapp/article/name').body.should == '/myapp'
|
1163
1160
|
end
|
1164
|
-
|
1161
|
+
|
1165
1162
|
describe "url" do
|
1166
1163
|
it "returns the fully qualified URL" do
|
1167
1164
|
my_app.get('/') { url }
|
1168
1165
|
rt.get('https://scorchedrb.com:73/myapp?something=true').body.should ==
|
1169
1166
|
'https://scorchedrb.com:73/myapp'
|
1170
1167
|
end
|
1171
|
-
|
1168
|
+
|
1172
1169
|
it "can append an optional path" do
|
1173
1170
|
my_app.get('/') { url('hello') }
|
1174
1171
|
rt.get('https://scorchedrb.com:73/myapp?something=true').body.should ==
|
1175
1172
|
'https://scorchedrb.com:73/myapp/hello'
|
1176
1173
|
end
|
1177
|
-
|
1174
|
+
|
1178
1175
|
it "returns the given URL if scheme detected" do
|
1179
1176
|
test_url = 'http://google.com/blah'
|
1180
1177
|
my_app.get('/') { url(test_url) }
|
1181
1178
|
rt.get('/myapp').body.should == test_url
|
1182
1179
|
end
|
1183
|
-
|
1180
|
+
|
1184
1181
|
it "generates URL from inside subcontroller defined with controller helper" do
|
1185
1182
|
root_app.controller '/sub2' do
|
1186
1183
|
get('/') { url('hi') }
|
@@ -1188,29 +1185,29 @@ module Scorched
|
|
1188
1185
|
rt.get('https://scorchedrb.com:73/sub2').body.should == 'https://scorchedrb.com:73/hi'
|
1189
1186
|
end
|
1190
1187
|
end
|
1191
|
-
|
1188
|
+
|
1192
1189
|
describe "absolute" do
|
1193
1190
|
it "returns an absolute URL path" do
|
1194
1191
|
my_app.get('/absolute') { absolute }
|
1195
1192
|
rt.get('http://scorchedrb.com/myapp/absolute?something=true').body.should == '/myapp'
|
1196
1193
|
end
|
1197
|
-
|
1194
|
+
|
1198
1195
|
it "returns a forward slash if script name is the root of the URL path" do
|
1199
1196
|
root_app.get('/') { absolute }
|
1200
1197
|
rt.get('http://scorchedrb.com').body.should == '/'
|
1201
1198
|
end
|
1202
|
-
|
1199
|
+
|
1203
1200
|
it "can append an optional path" do
|
1204
1201
|
my_app.get('/absolute') { absolute('hello') }
|
1205
1202
|
rt.get('http://scorchedrb.com/myapp/absolute?something=true').body.should == '/myapp/hello'
|
1206
1203
|
end
|
1207
|
-
|
1204
|
+
|
1208
1205
|
it "returns the given URL if scheme detected" do
|
1209
1206
|
test_url = 'http://google.com/blah'
|
1210
1207
|
my_app.get('/') { absolute(test_url) }
|
1211
1208
|
rt.get('/myapp').body.should == test_url
|
1212
1209
|
end
|
1213
|
-
|
1210
|
+
|
1214
1211
|
it "returns an absolute URL path for subcontroller defined with controller helper" do
|
1215
1212
|
root_app.controller '/sub2' do
|
1216
1213
|
get('/') { absolute }
|
@@ -1219,7 +1216,7 @@ module Scorched
|
|
1219
1216
|
end
|
1220
1217
|
end
|
1221
1218
|
end
|
1222
|
-
|
1219
|
+
|
1223
1220
|
describe "delegators" do
|
1224
1221
|
it "delegates captures" do
|
1225
1222
|
app.get('/:id') { captures[:id] }
|