scorched 0.6 → 0.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Milestones.md +14 -3
- data/README.md +5 -5
- data/docs/01_preface.md +1 -1
- data/docs/02_fundamentals/08_views.md +11 -3
- data/docs/03_further_reading/be_creative.md +1 -1
- data/docs/03_further_reading/code_reloading.md +24 -0
- data/docs/03_further_reading/running_unit_tests.md +6 -0
- data/lib/scorched.rb +2 -0
- data/lib/scorched/controller.rb +52 -3
- data/lib/scorched/options.rb +1 -1
- data/lib/scorched/response.rb +1 -1
- data/lib/scorched/version.rb +1 -1
- data/scorched.gemspec +1 -1
- data/spec/controller_spec.rb +215 -179
- data/spec/helper.rb +2 -1
- metadata +6 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bbeb1df9d3b27b4e455d9c0ee30d282da0875a58
|
4
|
+
data.tar.gz: bf7ee84acc65b7bd2cd355afdca30150ac8b8f6a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a546b0e44c56adb26cc23d5d0fe40a60485467a50639c05fd36fadd8ce7dab591de8ff06b73c73756739ace69ab34a56402e9179d49e56b7a4920993050292d4
|
7
|
+
data.tar.gz: 3f85d181a8db836196db23099b6d5b49a424bad7d2f56c9e714021127ddcb9c4cf61664ec24b251d0affbd2aa4ea7fd0ea542b87f2a5124ba3100bd202938611
|
data/Milestones.md
CHANGED
@@ -3,7 +3,17 @@ Milestones
|
|
3
3
|
|
4
4
|
Changelog
|
5
5
|
---------
|
6
|
-
|
6
|
+
### v0.7
|
7
|
+
* Logging preparations made. Now just have to decide on a logging strategy, such as what to log, how verbose the messages should be, etc.
|
8
|
+
* Environment-specific defaults added. The environment variable ``RACK_ENV`` is used to determine the current environment.
|
9
|
+
* Non-Development
|
10
|
+
* ``config[:static_dir] = false``
|
11
|
+
* Development
|
12
|
+
* ``config[:show_exceptions] = true``
|
13
|
+
* ``config[:logger] = Logger.new(STDOUT)``
|
14
|
+
* Add developer-friendly 404 error page. This is implemented as an after filter, and won't have any effect if the response body is set.
|
15
|
+
* ``absolute`` method now returns forward slash if script name is empty.
|
16
|
+
|
7
17
|
### v0.6
|
8
18
|
* ``view_config`` options hash renamed to ``render_defaults`` which better reflects its function.
|
9
19
|
|
@@ -70,7 +80,8 @@ Some of these remaining features may be broken out into a separate contributor l
|
|
70
80
|
|
71
81
|
Unlikely
|
72
82
|
--------
|
73
|
-
* Mutex locking option
|
83
|
+
* Mutex locking option - I'm of the opinion that the web server should be configured for the concurrency model of the application, rather than the framework.
|
84
|
+
* Using Rack::Protection by default - The problem here is that a good portion of Rack::Protection involves sessions, and given that Scorched doesn't itself load any session middleware, these components of Rack::Protection would have to be excluded. I wouldn't want to invoke a false sense of security
|
85
|
+
|
74
86
|
|
75
|
-
|
76
87
|
More things will be added to these lists as they're thought of and considered.
|
data/README.md
CHANGED
@@ -32,23 +32,23 @@ _**Note**: Scorched requires Ruby 2.0 as it makes use of a couple of new feature
|
|
32
32
|
|
33
33
|
The Errors of Our Past
|
34
34
|
----------------------
|
35
|
-
One of the
|
35
|
+
One of the mistakes made by a lot of other Ruby frameworks, was to not leverage the power of the class. The consequences of this made for some awkwardness. Helpers for example, are a classical reinvention of what classes and modules were already made to solve. Scorched implements Controllers as classes, which in addition to having their own DSL, allow defining and calling traditional instance methods. The decision to allow developers to implement helpers and other common functionality as proper methods not only makes Controllers somewhat more predictable and familiar, but of course allow such helpers to be inheritable via plain-old class inheritance.
|
36
36
|
|
37
37
|
Perhaps another design oversight of other frameworks, has been the lack of consideration for the hierarchical nature of websites, and the fact that sub-directories are often expected to inherit attributes of their parents. Scorched supports sub-controllers to any arbitrary depth, with each controllers configuration, filters, route conditions, etc, applied along the way. This can assist many areas of web development, including security, restful interfaces, and interchangeable content types.
|
38
38
|
|
39
39
|
|
40
40
|
Design Philosophy
|
41
41
|
-----------------
|
42
|
-
Scorched has a relatively simple design philosophy. The main objective is to keep Scorched lean and generic. Scorched refrains from expressing
|
42
|
+
Scorched has a relatively simple design philosophy. The main objective is to keep Scorched lean and generic. Scorched refrains from expressing any opinion about how you design and structure your application. The general idea is to give developers the constructs to quickly put together small, medium and even large websites and applications.
|
43
43
|
|
44
|
-
There's little need for a framework to be opinionated if the opinions of the developer can be quickly and easily built into it on a per-application basis. To do this effectively, developers really need to understand Scorched, and the best way to
|
44
|
+
There's little need for a framework to be opinionated if the opinions of the developer can be quickly and easily built into it on a per-application basis. To do this effectively, developers really need to understand Scorched, and the best way to facilitate that is to lower the learning curve by keeping the core design logical, predictable, and concise.
|
45
45
|
|
46
46
|
|
47
47
|
Magicians Not Welcome
|
48
48
|
---------------------
|
49
|
-
Scorched aims to be raw and transparent. Magic has no place
|
49
|
+
Scorched aims to be raw and transparent. Magic has no place. A thoughtful and simple design means there's no requirement for magic. Because of that, most developers should be able to master scorched in an evening.
|
50
50
|
|
51
|
-
Part of what keeps Scorched lightweight, is that unlike other lightweight web frameworks that attempt to hide Rack in the background, Scorched makes no such attempts, very rarely providing functionality that overlaps with
|
51
|
+
Part of what keeps Scorched lightweight, is that unlike other lightweight web frameworks that attempt to hide Rack in the background, Scorched makes no such attempts, very rarely providing functionality that overlaps with what's already provided by Rack. In fact, familiarity with Rack is somewhat of a pre-requisite to mastering Scorched.
|
52
52
|
|
53
53
|
|
54
54
|
First Impressions
|
data/docs/01_preface.md
CHANGED
@@ -3,4 +3,4 @@ Preface
|
|
3
3
|
|
4
4
|
_This is where I share with you all my infinite wisdom. It will come. In the mean time, know that the documentation is currently incomplete, and likely the victim of quite a few typos._
|
5
5
|
|
6
|
-
_As an early adopter, feel free to use the Github issue tracker to ask questions and request assistance._
|
6
|
+
_As an early adopter, feel free to use the Github issue tracker to ask questions and request assistance. Such questions will be used to further refine the documentation._
|
@@ -6,9 +6,17 @@ Scorched uses Tilt to render templates in various supported formats. Because of
|
|
6
6
|
``render`` can take a file path or a string as the template. If a symbol is given, it assumes it's a file path, were as a string is assumed to be the template markup. ``render`` can also takes a set of options.
|
7
7
|
|
8
8
|
* ``:dir`` - The directory containing the views. This can be absolute or relative to the current working directory.
|
9
|
-
* ``:layout`` - The template to render _around_ the view.
|
9
|
+
* ``:layout`` - The template to render _around_ the view.
|
10
10
|
* ``:engine`` - The template engine to use if it can't be derived from the file name. This is always required for string templates. Can be any string or symbol that Tilt recognises, e.g :erb, :haml, :sass, etc.
|
11
11
|
|
12
|
-
Any unrecognised options are passed through to Tilt and the corresponding rendering engine.
|
12
|
+
Any unrecognised options are passed through to Tilt and the corresponding rendering engine. A common example being the ``:locals`` option, used to set local variables made available within the scope of the view.
|
13
13
|
|
14
|
-
Finally, ``render`` takes an optional block to be _yielded_ within the view being rendered, if supported by the rendering engine.
|
14
|
+
Finally, ``render`` takes an optional block to be _yielded_ within the view being rendered, if supported by the rendering engine. Layout's use this feature.
|
15
|
+
|
16
|
+
Layouts
|
17
|
+
-------
|
18
|
+
When a layout is given, a subsequent call to ``render`` is made, with the rendered result of the main template given as the block to be yielded. The defined ``:layout`` is provided as the first argument on the sub-sequent call to ``render``, so the same rules apply. Layouts inherit the options of the main template being rendered.
|
19
|
+
|
20
|
+
Partials
|
21
|
+
--------
|
22
|
+
There are cases where a you may want a view to be composed of more than just a layout and a single view. The view may contain one or more sub-views, commonly referred to as partials. Scorched makes provisions for this by ignoring the default layout when ``render`` is called within a view, hence negating the requirement to explicitly override the layout.
|
@@ -0,0 +1,24 @@
|
|
1
|
+
Code Reloading
|
2
|
+
==============
|
3
|
+
|
4
|
+
The difficulties, or rather impossibilities, of doing in-process code reloading in Ruby have been well-documented. Scorched therefore makes no attempt to implement in form of such code reloading. There are many out-of-process reloading solutions. These all essentially reboot your application, reloading all dependancies. This provides an obvious incentive to keep your application boot times as fast as possible.
|
5
|
+
|
6
|
+
A sub-set of the most popular application reloaders are detailed below.
|
7
|
+
|
8
|
+
Rerun
|
9
|
+
-----
|
10
|
+
Rerun is a general purpose gem (``gem install rerun``) for watching files and rerunning some command when any of those files change. The following example uses rerun to watch for changes to ".rb" and ".ru" files anywhere in the current directory tree. If a change is made, any previous instance of ``rackup`` are shutdown and restarted.
|
11
|
+
|
12
|
+
rerun -p "**/*.{rb,ru}" rackup
|
13
|
+
|
14
|
+
Shotgun
|
15
|
+
-------
|
16
|
+
Unlike Rerun, Shotgun doesn't do any file watching. It instead reloads your application on every request. This sounds slow, but rerun uses an efficient technique of forking the application server and reloading your application. For applications that are quick to start, this method is generally preferred. Shotgun was used for example while developing http://scorchedrb.com.
|
17
|
+
|
18
|
+
shotgun
|
19
|
+
|
20
|
+
Phusion Passenger
|
21
|
+
-----------------
|
22
|
+
The popular Apache/Nginx module for hosting Rack applications, Phusion Passenger, can be configured to reload your application on every request much like Shotgun does. Passenger can be faster that Shogun, as you can let the underlying web server (Apache or Nginx) to take care of the static file serving, which avoids having to reload your application for every static file request.
|
23
|
+
|
24
|
+
To have Passenger automatically restart your application on every request, create a file named ``tmp/always_restart.txt`` in the root of your application directory. Passenger will automatically detect this file and behave as intended.
|
@@ -0,0 +1,6 @@
|
|
1
|
+
Running Unit Tests
|
2
|
+
==================
|
3
|
+
|
4
|
+
If doing any development on Scorched, such as if you want to fork it or contribute patches to it, you will probably want to run the suite of tests that accompany it. The few dependancies required for running the Scorched unit tests are installed either when you install the Scorched gem, or by running ``bundle`` in the root of the Scorched source tree.
|
5
|
+
|
6
|
+
All unit tests have been written using RSpec. To run the tests, ``cd`` into the root of the Scorched source tree from a terminal, and run ``rspec``.
|
data/lib/scorched.rb
CHANGED
data/lib/scorched/controller.rb
CHANGED
@@ -11,7 +11,8 @@ module Scorched
|
|
11
11
|
config << {
|
12
12
|
:strip_trailing_slash => :redirect, # :redirect => Strips and redirects URL ending in forward slash, :ignore => internally ignores trailing slash, false => does nothing.
|
13
13
|
:static_dir => 'public', # The directory Scorched should serve static files from. Set to false if web server or anything else is serving static files.
|
14
|
-
:logger =>
|
14
|
+
:logger => nil,
|
15
|
+
:show_exceptions => false
|
15
16
|
}
|
16
17
|
|
17
18
|
render_defaults << {
|
@@ -20,6 +21,13 @@ module Scorched
|
|
20
21
|
:engine => :erb
|
21
22
|
}
|
22
23
|
|
24
|
+
if ENV['RACK_ENV'] == 'development'
|
25
|
+
config[:logger] = Logger.new(STDOUT)
|
26
|
+
config[:show_exceptions] = true
|
27
|
+
else
|
28
|
+
config[:static_dir] = false
|
29
|
+
end
|
30
|
+
|
23
31
|
conditions << {
|
24
32
|
charset: proc { |charsets|
|
25
33
|
[*charsets].any? { |charset| request.env['rack-accept.request'].charset? charset }
|
@@ -53,10 +61,11 @@ module Scorched
|
|
53
61
|
use Rack::Accept
|
54
62
|
use Scorched::Static, this.config[:static_dir] if this.config[:static_dir]
|
55
63
|
use Rack::Logger, this.config[:logger] if this.config[:logger]
|
64
|
+
use Rack::ShowExceptions if this.config[:show_exceptions]
|
56
65
|
}
|
57
66
|
|
58
67
|
class << self
|
59
|
-
|
68
|
+
|
60
69
|
def mappings
|
61
70
|
@mappings ||= []
|
62
71
|
end
|
@@ -381,12 +390,46 @@ module Scorched
|
|
381
390
|
# Example: absolute('/style.css') #=> /myapp/style.css
|
382
391
|
def absolute(path = nil)
|
383
392
|
return path if path && URI.parse(path).scheme
|
384
|
-
if path
|
393
|
+
return_path = if path
|
385
394
|
[request.script_name, path].join('/').gsub(%r{/+}, '/')
|
386
395
|
else
|
387
396
|
request.script_name
|
388
397
|
end
|
398
|
+
return_path[0] == '/' ? return_path : return_path.insert(0, '/')
|
399
|
+
end
|
400
|
+
|
401
|
+
if ENV['RACK_ENV'] == 'development' &&
|
402
|
+
after do
|
403
|
+
if response.empty?
|
404
|
+
response.body = <<-HTML
|
405
|
+
<!DOCTYPE html>
|
406
|
+
<html>
|
407
|
+
<head>
|
408
|
+
<style type="text/css">
|
409
|
+
@import url(http://fonts.googleapis.com/css?family=Titillium+Web|Open+Sans:300italic,400italic,700italic,400,700,300);
|
410
|
+
html, body { height: 100%; width: 100%; margin: 0; font-family: 'Open Sans', 'Lucida Sans', 'Arial'; }
|
411
|
+
body { color: #333; display: table; }
|
412
|
+
#container { display: table-cell; vertical-align: middle; text-align: center; }
|
413
|
+
#container > * { display: inline-block; text-align: center; vertical-align: middle; }
|
414
|
+
#logo {
|
415
|
+
padding: 12px 24px 12px 120px; color: white; background: rgb(191, 64, 0);
|
416
|
+
font-family: 'Titillium Web', 'Lucida Sans', 'Arial'; font-size: 36pt; text-decoration: none;
|
417
|
+
}
|
418
|
+
h1 { margin-left: 18px; font-weight: 400; }
|
419
|
+
</style>
|
420
|
+
</head>
|
421
|
+
<body>
|
422
|
+
<div id="container">
|
423
|
+
<a id="logo" href="http://scorchedrb.com">Scorched</a>
|
424
|
+
<h1>404 Page Not Found</h1>
|
425
|
+
</div>
|
426
|
+
</body>
|
427
|
+
</html>
|
428
|
+
HTML
|
429
|
+
end
|
430
|
+
end
|
389
431
|
end
|
432
|
+
|
390
433
|
|
391
434
|
private
|
392
435
|
|
@@ -399,5 +442,11 @@ module Scorched
|
|
399
442
|
end
|
400
443
|
end
|
401
444
|
end
|
445
|
+
|
446
|
+
def log(type, message)
|
447
|
+
config[:logger].progname ||= 'Scorched'
|
448
|
+
type = Logger.const_get(type.to_s.upcase)
|
449
|
+
config[:logger].add(type, message)
|
450
|
+
end
|
402
451
|
end
|
403
452
|
end
|
data/lib/scorched/options.rb
CHANGED
data/lib/scorched/response.rb
CHANGED
@@ -17,7 +17,7 @@ module Scorched
|
|
17
17
|
|
18
18
|
# Automatically wraps the assigned value in an array if it doesn't respond to ``each``.
|
19
19
|
def body=(value)
|
20
|
-
super(value.respond_to?(:each) ? value : [value])
|
20
|
+
super(value.respond_to?(:each) ? value : [value].compact)
|
21
21
|
end
|
22
22
|
|
23
23
|
def finish(*args, &block)
|
data/lib/scorched/version.rb
CHANGED
data/scorched.gemspec
CHANGED
@@ -12,7 +12,7 @@ Gem::Specification.new 'scorched', Scorched::VERSION do |s|
|
|
12
12
|
s.rdoc_options = %w[--line-numbers --inline-source --title Scorched --encoding=UTF-8]
|
13
13
|
|
14
14
|
s.add_dependency 'rack', '~> 1.4'
|
15
|
-
s.add_dependency 'rack-accept', '~> 0.4
|
15
|
+
s.add_dependency 'rack-accept', '~> 0.4'
|
16
16
|
s.add_dependency 'tilt', '~> 1.3'
|
17
17
|
s.add_development_dependency 'rack-test', '~> 0.6'
|
18
18
|
s.add_development_dependency 'rspec', '~> 2.9'
|
data/spec/controller_spec.rb
CHANGED
@@ -206,6 +206,14 @@ module Scorched
|
|
206
206
|
rt.get('/dog').status.should == 404
|
207
207
|
rt.get('/').status.should == 200
|
208
208
|
end
|
209
|
+
|
210
|
+
it "leaves body empty if nil is returned" do
|
211
|
+
app.get('/') { }
|
212
|
+
app.after do
|
213
|
+
response.body.should == []
|
214
|
+
end
|
215
|
+
rt.get('/')
|
216
|
+
end
|
209
217
|
end
|
210
218
|
|
211
219
|
describe "sub-controllers" do
|
@@ -459,8 +467,8 @@ module Scorched
|
|
459
467
|
|
460
468
|
describe "configuration" do
|
461
469
|
describe "strip_trailing_slash" do
|
462
|
-
it "
|
463
|
-
app.config[:strip_trailing_slash]
|
470
|
+
it "can be set to strip trailing slash and redirect" do
|
471
|
+
app.config[:strip_trailing_slash] = :redirect
|
464
472
|
app.get('/test') { }
|
465
473
|
response = rt.get('/test/')
|
466
474
|
response.status.should == 307
|
@@ -486,8 +494,8 @@ module Scorched
|
|
486
494
|
end
|
487
495
|
|
488
496
|
describe "static_dir" do
|
489
|
-
it "
|
490
|
-
app.config[:static_dir]
|
497
|
+
it "can serve static file from the specific directory" do
|
498
|
+
app.config[:static_dir] = 'public'
|
491
499
|
response = rt.get('/static.txt')
|
492
500
|
response.status.should == 200
|
493
501
|
response.body.should == 'My static file!'
|
@@ -500,218 +508,246 @@ module Scorched
|
|
500
508
|
end
|
501
509
|
end
|
502
510
|
|
503
|
-
describe "
|
504
|
-
it "
|
505
|
-
|
506
|
-
app.get('/') {
|
507
|
-
rt.get('/')
|
508
|
-
|
511
|
+
describe "show_exceptions" do
|
512
|
+
it "shows debug-friendly error page for unhandled exceptions" do
|
513
|
+
app.config[:show_exceptions] = true
|
514
|
+
app.get('/') { raise RuntimeError, "Kablamo!" }
|
515
|
+
response = rt.get('/')
|
516
|
+
response.status.should == 500
|
517
|
+
response.body.should include('Rack::ShowExceptions')
|
518
|
+
end
|
519
|
+
|
520
|
+
it "can be disabled" do
|
521
|
+
app.config[:show_exceptions] = false
|
522
|
+
app.get('/') { raise RuntimeError, "Kablamo!" }
|
523
|
+
expect {
|
524
|
+
response = rt.get('/')
|
525
|
+
}.to raise_error(RuntimeError)
|
526
|
+
end
|
527
|
+
end
|
528
|
+
end
|
529
|
+
|
530
|
+
describe "sessions" do
|
531
|
+
it "provides convenience method for accessing the Rack session" do
|
532
|
+
rack_session = nil
|
533
|
+
app.get('/') { rack_session = session }
|
534
|
+
rt.get('/')
|
535
|
+
rack_session.should be_nil
|
536
|
+
app.middleware << proc { use Rack::Session::Cookie, secret: 'test' }
|
537
|
+
rt.get('/')
|
538
|
+
rack_session.should be_a(Rack::Session::Abstract::SessionHash)
|
539
|
+
end
|
540
|
+
|
541
|
+
describe "flash" do
|
542
|
+
before(:each) do
|
509
543
|
app.middleware << proc { use Rack::Session::Cookie, secret: 'test' }
|
510
|
-
rt.get('/')
|
511
|
-
rack_session.should be_a(Rack::Session::Abstract::SessionHash)
|
512
544
|
end
|
513
545
|
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
end
|
546
|
+
it "keeps session variables that live for one page load" do
|
547
|
+
app.get('/set') { flash[:cat] = 'meow' }
|
548
|
+
app.get('/get') { flash[:cat] }
|
518
549
|
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
it "always reads from the original request flash" do
|
529
|
-
app.get('/') do
|
530
|
-
flash[:counter] = flash[:counter] ? flash[:counter] + 1 : 0
|
531
|
-
flash[:counter].to_s
|
532
|
-
end
|
533
|
-
|
534
|
-
rt.get('/').body.should == ''
|
535
|
-
rt.get('/').body.should == '0'
|
536
|
-
rt.get('/').body.should == '1'
|
550
|
+
rt.get('/set')
|
551
|
+
rt.get('/get').body.should == 'meow'
|
552
|
+
rt.get('/get').body.should == ''
|
553
|
+
end
|
554
|
+
|
555
|
+
it "always reads from the original request flash" do
|
556
|
+
app.get('/') do
|
557
|
+
flash[:counter] = flash[:counter] ? flash[:counter] + 1 : 0
|
558
|
+
flash[:counter].to_s
|
537
559
|
end
|
538
560
|
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
end
|
561
|
+
rt.get('/').body.should == ''
|
562
|
+
rt.get('/').body.should == '0'
|
563
|
+
rt.get('/').body.should == '1'
|
564
|
+
end
|
565
|
+
|
566
|
+
it "can only remove flash variables if the flash object is accessed" do
|
567
|
+
app.get('/set') { flash[:cat] = 'meow' }
|
568
|
+
app.get('/get') { flash[:cat] }
|
569
|
+
app.get('/null') { }
|
549
570
|
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
app.get('/get_name') { flash(:names)[:jeff] }
|
555
|
-
|
556
|
-
rt.get('/set_animal')
|
557
|
-
rt.get('/set_name')
|
558
|
-
rt.get('/get_animal').body.should == 'meow'
|
559
|
-
rt.get('/get_name').body.should == 'male'
|
560
|
-
rt.get('/get_animal').body.should == ''
|
561
|
-
rt.get('/get_name').body.should == ''
|
562
|
-
end
|
571
|
+
rt.get('/set')
|
572
|
+
rt.get('/null')
|
573
|
+
rt.get('/get').body.should == 'meow'
|
574
|
+
rt.get('/get').body.should == ''
|
563
575
|
end
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
app.get('/') {
|
569
|
-
app.
|
570
|
-
app.post('/goodbye') { cookie :test, {value: 'goodbye', expires: Time.now() + 999999 } }
|
571
|
-
app.delete('/') { cookie :test, nil }
|
572
|
-
app.delete('/alt') { cookie :test, {value: nil} }
|
576
|
+
|
577
|
+
it "can keep multiple sets of flash session variables" do
|
578
|
+
app.get('/set_animal') { flash(:animals)[:cat] = 'meow' }
|
579
|
+
app.get('/get_animal') { flash(:animals)[:cat] }
|
580
|
+
app.get('/set_name') { flash(:names)[:jeff] = 'male' }
|
581
|
+
app.get('/get_name') { flash(:names)[:jeff] }
|
573
582
|
|
574
|
-
rt.get('/')
|
575
|
-
rt.
|
576
|
-
rt.get('/').body.should == '
|
577
|
-
rt.
|
578
|
-
rt.get('/').body.should == '
|
579
|
-
rt.
|
580
|
-
rt.get('/').body.should == ''
|
581
|
-
rt.delete('/alt')
|
582
|
-
rt.get('/').body.should == ''
|
583
|
+
rt.get('/set_animal')
|
584
|
+
rt.get('/set_name')
|
585
|
+
rt.get('/get_animal').body.should == 'meow'
|
586
|
+
rt.get('/get_name').body.should == 'male'
|
587
|
+
rt.get('/get_animal').body.should == ''
|
588
|
+
rt.get('/get_name').body.should == ''
|
583
589
|
end
|
584
590
|
end
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
591
|
+
end
|
592
|
+
|
593
|
+
describe "cookie helper" do
|
594
|
+
it "sets, retrieves and deletes cookies" do
|
595
|
+
app.get('/') { cookie :test }
|
596
|
+
app.post('/') { cookie :test, 'hello' }
|
597
|
+
app.post('/goodbye') { cookie :test, {value: 'goodbye', expires: Time.now() + 999999 } }
|
598
|
+
app.delete('/') { cookie :test, nil }
|
599
|
+
app.delete('/alt') { cookie :test, {value: nil} }
|
600
|
+
|
601
|
+
rt.get('/').body.should == ''
|
602
|
+
rt.post('/')
|
603
|
+
rt.get('/').body.should == 'hello'
|
604
|
+
rt.post('/goodbye')
|
605
|
+
rt.get('/').body.should == 'goodbye'
|
606
|
+
rt.delete('/')
|
607
|
+
rt.get('/').body.should == ''
|
608
|
+
rt.delete('/alt')
|
609
|
+
rt.get('/').body.should == ''
|
610
|
+
end
|
611
|
+
end
|
612
|
+
|
613
|
+
describe "rendering" do
|
614
|
+
before(:each) do
|
615
|
+
app.render_defaults.each { |k,v| app.render_defaults[k] = nil }
|
616
|
+
end
|
590
617
|
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
end
|
595
|
-
rt.get('/')
|
618
|
+
it "can render a file, relative to the application root" do
|
619
|
+
app.get('/') do
|
620
|
+
render(:'views/main.erb').should == "3 for me"
|
596
621
|
end
|
622
|
+
rt.get('/')
|
623
|
+
end
|
597
624
|
|
598
|
-
|
599
|
-
|
600
|
-
|
601
|
-
end
|
602
|
-
rt.get('/')
|
625
|
+
it "can render a string" do
|
626
|
+
app.get('/') do
|
627
|
+
render('<%= 1 + 1 %> for you', engine: :erb).should == "2 for you"
|
603
628
|
end
|
629
|
+
rt.get('/')
|
630
|
+
end
|
604
631
|
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
end
|
609
|
-
rt.get('/')
|
632
|
+
it "takes an optional view directory, relative to the application root" do
|
633
|
+
app.get('/') do
|
634
|
+
render(:'main.erb', dir: 'views').should == "3 for me"
|
610
635
|
end
|
636
|
+
rt.get('/')
|
637
|
+
end
|
611
638
|
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
end
|
616
|
-
rt.get('/')
|
639
|
+
it "takes an optional block to be yielded by the view" do
|
640
|
+
app.get('/') do
|
641
|
+
render(:'views/layout.erb'){ "in the middle" }.should == "(in the middle)"
|
617
642
|
end
|
643
|
+
rt.get('/')
|
644
|
+
end
|
618
645
|
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
end
|
623
|
-
rt.get('/')
|
646
|
+
it "renders the given layout" do
|
647
|
+
app.get('/') do
|
648
|
+
render(:'views/main.erb', layout: :'views/layout.erb').should == "(3 for me)"
|
624
649
|
end
|
650
|
+
rt.get('/')
|
651
|
+
end
|
625
652
|
|
626
|
-
|
627
|
-
|
628
|
-
|
629
|
-
|
630
|
-
|
631
|
-
|
632
|
-
end
|
633
|
-
app.render_defaults[:dir] = 'views'
|
634
|
-
rt.get('/')
|
635
|
-
rt.get('/full_path')
|
653
|
+
it "merges options with view config" do
|
654
|
+
app.get('/') do
|
655
|
+
render(:'main.erb').should == "3 for me"
|
656
|
+
end
|
657
|
+
app.get('/full_path') do
|
658
|
+
render(:'views/main.erb', {layout: :'views/layout.erb', dir: nil}).should == "(3 for me)"
|
636
659
|
end
|
660
|
+
app.render_defaults[:dir] = 'views'
|
661
|
+
rt.get('/')
|
662
|
+
rt.get('/full_path')
|
663
|
+
end
|
637
664
|
|
638
|
-
|
639
|
-
|
640
|
-
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
649
|
-
end
|
650
|
-
rt.get('/str')
|
651
|
-
rt.get('/erb_file')
|
652
|
-
rt.get('/erb_string')
|
665
|
+
it "derived template engine overrides specified engine" do
|
666
|
+
app.render_defaults[:dir] = 'views'
|
667
|
+
app.render_defaults[:engine] = :erb
|
668
|
+
app.get('/str') do
|
669
|
+
render(:'other.str').should == "hello hello"
|
670
|
+
end
|
671
|
+
app.get('/erb_file') do
|
672
|
+
render(:main).should == "3 for me"
|
673
|
+
end
|
674
|
+
app.get('/erb_string') do
|
675
|
+
render('<%= 1 + 1 %> for you').should == "2 for you"
|
653
676
|
end
|
677
|
+
rt.get('/str')
|
678
|
+
rt.get('/erb_file')
|
679
|
+
rt.get('/erb_string')
|
680
|
+
end
|
654
681
|
|
655
|
-
|
656
|
-
|
657
|
-
|
658
|
-
|
659
|
-
end
|
660
|
-
rt.get('/').body.should == '({1 for none})'
|
682
|
+
it "ignores default layout when called within a view" do
|
683
|
+
app.render_defaults << {:dir => 'views', :layout => :layout, :engine => :erb}
|
684
|
+
app.get('/') do
|
685
|
+
render :composer
|
661
686
|
end
|
687
|
+
rt.get('/').body.should == '({1 for none})'
|
688
|
+
end
|
689
|
+
end
|
690
|
+
|
691
|
+
describe "url helpers" do
|
692
|
+
let(:my_app) do
|
693
|
+
Class.new(Scorched::Controller)
|
694
|
+
end
|
695
|
+
|
696
|
+
let(:root_app) do
|
697
|
+
Class.new(Scorched::Controller)
|
662
698
|
end
|
663
699
|
|
664
|
-
|
665
|
-
|
666
|
-
|
700
|
+
let(:app) do
|
701
|
+
this = self
|
702
|
+
builder = Rack::Builder.new
|
703
|
+
builder.map('/myapp') { run this.my_app }
|
704
|
+
builder.map('/') { run this.root_app }
|
705
|
+
builder.to_app
|
706
|
+
end
|
707
|
+
|
708
|
+
describe "url" do
|
709
|
+
it "returns the fully qualified URL" do
|
710
|
+
my_app.get('/') { url }
|
711
|
+
rt.get('https://scorchedrb.com:73/myapp?something=true').body.should ==
|
712
|
+
'https://scorchedrb.com:73/myapp'
|
667
713
|
end
|
668
714
|
|
669
|
-
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
builder.to_app
|
715
|
+
it "can append an optional path" do
|
716
|
+
my_app.get('/') { url('hello') }
|
717
|
+
rt.get('https://scorchedrb.com:73/myapp?something=true').body.should ==
|
718
|
+
'https://scorchedrb.com:73/myapp/hello'
|
674
719
|
end
|
675
720
|
|
676
|
-
|
677
|
-
|
678
|
-
|
679
|
-
|
680
|
-
|
681
|
-
|
682
|
-
|
683
|
-
|
684
|
-
|
685
|
-
|
686
|
-
|
687
|
-
end
|
688
|
-
|
689
|
-
it "returns the given URL if scheme detected" do
|
690
|
-
test_url = 'http://google.com/blah'
|
691
|
-
myapp.get('/') { url(test_url) }
|
692
|
-
rt.get('/myapp').body.should == test_url
|
693
|
-
end
|
721
|
+
it "returns the given URL if scheme detected" do
|
722
|
+
test_url = 'http://google.com/blah'
|
723
|
+
my_app.get('/') { url(test_url) }
|
724
|
+
rt.get('/myapp').body.should == test_url
|
725
|
+
end
|
726
|
+
end
|
727
|
+
|
728
|
+
describe "absolute" do
|
729
|
+
it "returns an absolute URL path" do
|
730
|
+
my_app.get('/absolute') { absolute }
|
731
|
+
rt.get('http://scorchedrb.com/myapp/absolute?something=true').body.should == '/myapp'
|
694
732
|
end
|
695
733
|
|
696
|
-
|
697
|
-
|
698
|
-
|
699
|
-
|
700
|
-
|
701
|
-
|
702
|
-
|
703
|
-
|
704
|
-
|
705
|
-
|
706
|
-
|
707
|
-
|
708
|
-
|
709
|
-
|
710
|
-
rt.get('/myapp').body.should == test_url
|
711
|
-
end
|
734
|
+
it "returns a forward slash if script name is the root of the URL path" do
|
735
|
+
root_app.get('/') { absolute }
|
736
|
+
rt.get('http://scorchedrb.com').body.should == '/'
|
737
|
+
end
|
738
|
+
|
739
|
+
it "can append an optional path" do
|
740
|
+
my_app.get('/absolute') { absolute('hello') }
|
741
|
+
rt.get('http://scorchedrb.com/myapp/absolute?something=true').body.should == '/myapp/hello'
|
742
|
+
end
|
743
|
+
|
744
|
+
it "returns the given URL if scheme detected" do
|
745
|
+
test_url = 'http://google.com/blah'
|
746
|
+
my_app.get('/') { absolute(test_url) }
|
747
|
+
rt.get('/myapp').body.should == test_url
|
712
748
|
end
|
713
749
|
end
|
714
|
-
|
715
750
|
end
|
751
|
+
|
716
752
|
end
|
717
753
|
end
|
data/spec/helper.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: scorched
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: '0.
|
4
|
+
version: '0.7'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tom Wardrop
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-03-
|
11
|
+
date: 2013-03-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rack
|
@@ -30,14 +30,14 @@ dependencies:
|
|
30
30
|
requirements:
|
31
31
|
- - ~>
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: 0.4
|
33
|
+
version: '0.4'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - ~>
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: 0.4
|
40
|
+
version: '0.4'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: tilt
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -102,6 +102,8 @@ files:
|
|
102
102
|
- docs/02_fundamentals/08_views.md
|
103
103
|
- docs/02_fundamentals/09_sharing_request_state.md
|
104
104
|
- docs/03_further_reading/be_creative.md
|
105
|
+
- docs/03_further_reading/code_reloading.md
|
106
|
+
- docs/03_further_reading/running_unit_tests.md
|
105
107
|
- examples/file_upload.ru
|
106
108
|
- examples/media_types.ru
|
107
109
|
- lib/scorched.rb
|