ramaze 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Rakefile +4 -12
- data/bin/ramaze +95 -171
- data/doc/CHANGELOG +387 -4
- data/doc/README +81 -13
- data/doc/meta/announcement.txt +51 -8
- data/doc/meta/configuration.txt +17 -34
- data/doc/meta/internals.txt +34 -4
- data/doc/migrate/1110_to_1111.txt +131 -0
- data/doc/readme_chunks/features.txt +81 -12
- data/doc/readme_chunks/installing.txt +0 -1
- data/doc/tutorial/todolist.html +293 -65
- data/doc/tutorial/{todolist.txt → todolist.mkd} +251 -51
- data/examples/blog/main.rb +1 -1
- data/examples/blog/src/model.rb +0 -1
- data/examples/hello.rb +2 -5
- data/examples/templates/template/external.haml +5 -5
- data/examples/templates/template/external.liquid +1 -1
- data/examples/templates/template/external.mab +8 -8
- data/examples/templates/template/external.rem +30 -0
- data/examples/templates/template/external.rhtml +6 -7
- data/examples/templates/template/external.zmr +13 -9
- data/examples/templates/template_amrita2.rb +8 -8
- data/examples/templates/template_erubis.rb +11 -11
- data/examples/templates/template_ezamar.rb +9 -11
- data/examples/templates/template_haml.rb +13 -13
- data/examples/templates/template_liquid.rb +10 -10
- data/examples/templates/template_markaby.rb +13 -10
- data/examples/templates/template_remarkably.rb +59 -0
- data/examples/todolist/main.rb +1 -7
- data/examples/todolist/src/controller/main.rb +26 -13
- data/examples/todolist/src/element/page.rb +5 -0
- data/examples/whywiki/main.rb +1 -1
- data/lib/proto/main.rb +0 -8
- data/lib/proto/public/css/ramaze_error.css +12 -4
- data/lib/proto/public/error.zmr +6 -25
- data/lib/ramaze.rb +35 -245
- data/lib/ramaze/action.rb +21 -0
- data/lib/ramaze/adapter.rb +94 -29
- data/lib/ramaze/adapter/base.rb +57 -0
- data/lib/ramaze/adapter/mongrel.rb +12 -19
- data/lib/ramaze/adapter/webrick.rb +21 -20
- data/lib/ramaze/cache.rb +47 -3
- data/lib/ramaze/cache/memcached.rb +22 -0
- data/lib/ramaze/cache/yaml_store.rb +19 -0
- data/lib/ramaze/controller.rb +47 -271
- data/lib/ramaze/controller/error.rb +43 -0
- data/lib/ramaze/controller/render.rb +90 -0
- data/lib/ramaze/controller/resolve.rb +147 -0
- data/lib/ramaze/dispatcher.rb +41 -9
- data/lib/ramaze/dispatcher/file.rb +1 -1
- data/lib/ramaze/global.rb +73 -158
- data/lib/ramaze/global/dsl.rb +29 -0
- data/lib/ramaze/global/globalstruct.rb +90 -0
- data/lib/ramaze/helper.rb +1 -1
- data/lib/ramaze/helper/aspect.rb +39 -179
- data/lib/ramaze/helper/cache.rb +8 -9
- data/lib/ramaze/helper/cgi.rb +23 -0
- data/lib/ramaze/helper/file.rb +3 -0
- data/lib/ramaze/helper/inform.rb +3 -0
- data/lib/ramaze/helper/link.rb +56 -63
- data/lib/ramaze/helper/nitroform.rb +4 -0
- data/lib/ramaze/helper/redirect.rb +1 -1
- data/lib/ramaze/inform.rb +6 -2
- data/lib/ramaze/inform/analogger.rb +5 -1
- data/lib/ramaze/inform/hub.rb +1 -1
- data/lib/ramaze/inform/informing.rb +7 -0
- data/lib/ramaze/snippets/kernel/aquire.rb +2 -0
- data/lib/ramaze/snippets/kernel/constant.rb +2 -0
- data/lib/ramaze/snippets/kernel/pretty_inspect.rb +2 -0
- data/lib/ramaze/snippets/object/traits.rb +4 -0
- data/lib/ramaze/snippets/openstruct/temp.rb +3 -0
- data/lib/ramaze/snippets/string/DIVIDE.rb +2 -0
- data/lib/ramaze/snippets/string/camel_case.rb +2 -0
- data/lib/ramaze/snippets/string/color.rb +2 -0
- data/lib/ramaze/snippets/string/each.rb +2 -0
- data/lib/ramaze/snippets/string/snake_case.rb +3 -0
- data/lib/ramaze/snippets/struct/fill.rb +8 -2
- data/lib/ramaze/snippets/struct/values_at.rb +16 -0
- data/lib/ramaze/snippets/symbol/to_proc.rb +3 -0
- data/lib/ramaze/sourcereload.rb +89 -0
- data/lib/ramaze/template.rb +21 -12
- data/lib/ramaze/template/amrita2.rb +6 -6
- data/lib/ramaze/template/erubis.rb +4 -9
- data/lib/ramaze/template/ezamar.rb +13 -57
- data/lib/ramaze/template/ezamar/element.rb +10 -12
- data/lib/ramaze/template/ezamar/engine.rb +40 -101
- data/lib/ramaze/template/ezamar/morpher.rb +3 -3
- data/lib/ramaze/template/haml.rb +3 -6
- data/lib/ramaze/template/liquid.rb +4 -9
- data/lib/ramaze/template/markaby.rb +16 -22
- data/lib/ramaze/template/remarkably.rb +28 -0
- data/lib/ramaze/tool/mime.rb +2 -0
- data/lib/ramaze/tool/record.rb +6 -0
- data/lib/ramaze/trinity/request.rb +44 -54
- data/lib/ramaze/trinity/response.rb +1 -1
- data/lib/ramaze/trinity/session.rb +15 -37
- data/lib/ramaze/version.rb +1 -1
- data/rake_tasks/gem.rake +2 -2
- data/rake_tasks/maintaince.rake +42 -1
- data/rake_tasks/spec.rake +45 -0
- data/spec/examples/caching.rb +1 -1
- data/spec/examples/simple.rb +1 -1
- data/spec/examples/templates/template_amrita2.rb +1 -0
- data/spec/examples/templates/template_erubis.rb +2 -1
- data/spec/examples/templates/template_ezamar.rb +1 -1
- data/spec/examples/templates/template_haml.rb +2 -1
- data/spec/examples/templates/template_liquid.rb +2 -1
- data/spec/examples/templates/template_markaby.rb +2 -1
- data/spec/examples/templates/template_remarkably.rb +22 -0
- data/spec/examples/todolist.rb +125 -0
- data/spec/helper.rb +2 -23
- data/spec/helper/minimal.rb +20 -0
- data/spec/helper/mock_http.rb +24 -30
- data/spec/helper/simple_http.rb +2 -2
- data/spec/helper/wrap.rb +6 -9
- data/spec/ramaze/adapter.rb +1 -1
- data/spec/ramaze/adapter/record.rb +31 -0
- data/spec/ramaze/cache.rb +41 -54
- data/spec/ramaze/controller.rb +121 -137
- data/spec/ramaze/controller/template/list.xhtml +1 -0
- data/spec/ramaze/controller/template/other/greet/other.xhtml +1 -0
- data/spec/ramaze/controller/template_resolving.rb +27 -3
- data/spec/ramaze/element.rb +11 -7
- data/spec/ramaze/error.rb +1 -1
- data/spec/ramaze/gestalt.rb +2 -0
- data/spec/ramaze/helper/aspect.rb +30 -21
- data/spec/ramaze/helper/auth.rb +1 -1
- data/spec/ramaze/helper/cache.rb +2 -1
- data/spec/ramaze/helper/form.rb +14 -11
- data/spec/ramaze/helper/link.rb +18 -41
- data/spec/ramaze/localize.rb +29 -2
- data/spec/ramaze/morpher.rb +23 -12
- data/spec/ramaze/params.rb +46 -24
- data/spec/ramaze/request.rb +6 -2
- data/spec/ramaze/store/yaml.rb +5 -0
- data/spec/ramaze/template.rb +22 -27
- data/spec/ramaze/template/amrita2.rb +1 -2
- data/spec/ramaze/template/erubis.rb +1 -1
- data/spec/ramaze/template/ezamar.rb +1 -2
- data/spec/ramaze/template/haml.rb +2 -2
- data/spec/ramaze/template/haml/with_vars.haml +1 -1
- data/spec/ramaze/template/liquid.rb +1 -1
- data/spec/ramaze/template/markaby.rb +1 -1
- data/spec/ramaze/template/remarkably.rb +56 -0
- data/spec/ramaze/template/remarkably/external.rem +8 -0
- data/spec/ramaze/template/remarkably/sum.rem +1 -0
- metadata +38 -63
- data/doc/README.html +0 -637
- data/doc/allison/LICENSE +0 -184
- data/doc/allison/README +0 -37
- data/doc/allison/allison.css +0 -299
- data/doc/allison/allison.gif +0 -0
- data/doc/allison/allison.js +0 -307
- data/doc/allison/allison.rb +0 -287
- data/doc/allison/cache/BODY +0 -588
- data/doc/allison/cache/CLASS_INDEX +0 -4
- data/doc/allison/cache/CLASS_PAGE +0 -1
- data/doc/allison/cache/FILE_INDEX +0 -4
- data/doc/allison/cache/FILE_PAGE +0 -1
- data/doc/allison/cache/FONTS +0 -1
- data/doc/allison/cache/FR_INDEX_BODY +0 -1
- data/doc/allison/cache/IMGPATH +0 -1
- data/doc/allison/cache/INDEX +0 -1
- data/doc/allison/cache/JAVASCRIPT +0 -307
- data/doc/allison/cache/METHOD_INDEX +0 -4
- data/doc/allison/cache/METHOD_LIST +0 -1
- data/doc/allison/cache/SRC_PAGE +0 -1
- data/doc/allison/cache/STYLE +0 -321
- data/doc/allison/cache/URL +0 -1
- data/doc/changes.txt +0 -3375
- data/doc/changes.xml +0 -3378
- data/examples/todolist/conf/benchmark.yaml +0 -35
- data/examples/todolist/conf/debug.yaml +0 -34
- data/examples/todolist/conf/live.yaml +0 -33
- data/examples/todolist/conf/silent.yaml +0 -31
- data/examples/todolist/conf/stage.yaml +0 -33
- data/examples/todolist/public/css/coderay.css +0 -105
- data/examples/todolist/public/css/ramaze_error.css +0 -42
- data/lib/proto/conf/benchmark.yaml +0 -21
- data/lib/proto/conf/debug.yaml +0 -21
- data/lib/proto/conf/live.yaml +0 -21
- data/lib/proto/conf/silent.yaml +0 -21
- data/lib/proto/conf/stage.yaml +0 -21
- data/lib/proto/public/css/coderay.css +0 -105
- data/lib/ramaze/http_status.rb +0 -66
- data/lib/ramaze/snippets/hash/keys_to_sym.rb +0 -19
- data/lib/ramaze/snippets/kernel/method.rb +0 -26
- data/lib/ramaze/snippets/method/name.rb +0 -22
- data/lib/ramaze/snippets/ramaze/autoreload.rb +0 -135
- data/lib/ramaze/snippets/rdoc/usage_no_exit.rb +0 -65
- data/spec/all.rb +0 -32
- data/spec/ramaze/conf/locale_de.yaml +0 -6
- data/spec/ramaze/conf/locale_en.yaml +0 -6
- data/spec/ramaze/dependencies.rb +0 -16
- data/spec/ramaze/global.rb +0 -44
|
@@ -22,6 +22,11 @@ Ramaze offers following features at the moment:
|
|
|
22
22
|
CGI is the Common Gateway Interface and is one of the most basic ways
|
|
23
23
|
to integrate into Webservers like Apache, Lighttpd or Nginx.
|
|
24
24
|
|
|
25
|
+
* FCGI
|
|
26
|
+
|
|
27
|
+
Improvment of CGI as it doesn't start up a new connection to Ramaze on
|
|
28
|
+
every request.
|
|
29
|
+
|
|
25
30
|
|
|
26
31
|
* Templates
|
|
27
32
|
* [Amrita2](http://amrita2.rubyforge.org/)
|
|
@@ -42,13 +47,18 @@ Ramaze offers following features at the moment:
|
|
|
42
47
|
Liquid's syntax and parse model are inspired by Django templates, as well
|
|
43
48
|
as PHP's smarty.
|
|
44
49
|
|
|
50
|
+
* [Remarkably](http://rubyforge.org/projects/remarkably)
|
|
51
|
+
|
|
52
|
+
Remarkably is a very tiny Markaby-like XML builder
|
|
53
|
+
|
|
45
54
|
* [Markaby](http://code.whytheluckystiff.net/markaby/)
|
|
46
55
|
|
|
47
56
|
Markaby means Markup as Ruby.
|
|
48
57
|
|
|
49
58
|
* Ezamar
|
|
50
59
|
|
|
51
|
-
A simple homage to [Nitro](http://nitroproject.org)s templating
|
|
60
|
+
A simple homage to [Nitro](http://nitroproject.org)s templating, is shipped
|
|
61
|
+
together with Ramaze.
|
|
52
62
|
|
|
53
63
|
* Cache
|
|
54
64
|
* Hash
|
|
@@ -56,19 +66,78 @@ Ramaze offers following features at the moment:
|
|
|
56
66
|
* MemCache
|
|
57
67
|
|
|
58
68
|
* Helper
|
|
59
|
-
*
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
+
* Active by default
|
|
70
|
+
* CGI
|
|
71
|
+
|
|
72
|
+
Shortcuts for escape/unescape of the CGI module.
|
|
73
|
+
|
|
74
|
+
* File
|
|
75
|
+
|
|
76
|
+
Helps you serving files from your Controller.
|
|
77
|
+
|
|
78
|
+
* Flash
|
|
79
|
+
|
|
80
|
+
Store a couple of values for one request associated with a session.
|
|
81
|
+
|
|
82
|
+
* Link
|
|
83
|
+
|
|
84
|
+
Easier linking to the various parts of your applications Controllers and
|
|
85
|
+
Actions.
|
|
86
|
+
|
|
87
|
+
* Redirect
|
|
88
|
+
|
|
89
|
+
Easy redirection.
|
|
90
|
+
|
|
91
|
+
* Optional
|
|
92
|
+
* Aspect
|
|
93
|
+
|
|
94
|
+
Allows you to wrap different Actions on your Controller with code.
|
|
95
|
+
|
|
96
|
+
* Auth
|
|
97
|
+
|
|
98
|
+
Simple way to add basic authentication.
|
|
99
|
+
|
|
100
|
+
* Cache
|
|
101
|
+
|
|
102
|
+
Easy caching Actions and values.
|
|
103
|
+
|
|
104
|
+
* Feed
|
|
105
|
+
|
|
106
|
+
Programmatically generate feeds from any Class.
|
|
107
|
+
|
|
108
|
+
* Form
|
|
109
|
+
|
|
110
|
+
In development, help appreciated.
|
|
111
|
+
|
|
112
|
+
* Identity
|
|
113
|
+
|
|
114
|
+
For ease of use of the OpenID authentication mechanism.
|
|
115
|
+
|
|
116
|
+
* Inform
|
|
117
|
+
|
|
118
|
+
Wrapping the functionality of Ramazes logging facilities.
|
|
119
|
+
|
|
120
|
+
* Markaby
|
|
121
|
+
|
|
122
|
+
Allows you to use Markaby in your Controller without having it as the
|
|
123
|
+
default templating engine.
|
|
124
|
+
|
|
125
|
+
* Nitroform
|
|
126
|
+
|
|
127
|
+
Hooks up on nitros form builder to help you creating forms from Og
|
|
128
|
+
objects.
|
|
129
|
+
|
|
130
|
+
* OpenID
|
|
131
|
+
|
|
132
|
+
Authentication via OpenID made easy.
|
|
133
|
+
|
|
134
|
+
* Stack
|
|
135
|
+
|
|
136
|
+
Allows you to use a call/answer mechanism for things like redirection to the
|
|
137
|
+
site a user entered login-forms from.
|
|
69
138
|
|
|
70
139
|
* Various
|
|
71
140
|
* Sessions
|
|
72
141
|
* Global configuration system
|
|
73
142
|
* Simple request/response handling
|
|
74
|
-
* Custom Error-handling
|
|
143
|
+
* Custom sophisticated Error-handling
|
data/doc/tutorial/todolist.html
CHANGED
|
@@ -22,7 +22,30 @@
|
|
|
22
22
|
<meta content="text/html; charset=UTF-8" http-equiv="content-type" />
|
|
23
23
|
</head>
|
|
24
24
|
<body>
|
|
25
|
-
|
|
25
|
+
|
|
26
|
+
<h1>To-do List Tutorial</h1>
|
|
27
|
+
|
|
28
|
+
<div class="menu">
|
|
29
|
+
<h3>Table of Contents</h3>
|
|
30
|
+
<li>
|
|
31
|
+
<ol><a href="#Step_Zero,_Introduction">Step Zero, Introduction</a></ol>
|
|
32
|
+
<ol><a href="#First_Step,_Create">First Step, Create</a></ol>
|
|
33
|
+
<ol><a href="#Second_Step,_M,_like_Model">Second Step, M, like Model</a></ol>
|
|
34
|
+
<ol><a href="#Third_Step,_V,_like_View">Third Step, V, like View</a></ol>
|
|
35
|
+
<ol><a href="#Fourth_Step,_C,_like_Controller">Fourth Step, C, like Controller</a></ol>
|
|
36
|
+
<ol><a href="#Fifth_Step,_getting_dynamic">Fifth Step, getting dynamic</a></ol>
|
|
37
|
+
<ol><a href="#Sixth_Step,_open_and_close_tasks">Sixth Step, open and close tasks</a></ol>
|
|
38
|
+
<ol><a href="#Seventh_Step,_delete_tasks">Seventh Step, delete tasks</a></ol>
|
|
39
|
+
<ol><a href="#Eighth_Step,_Elements">Eighth Step, Elements</a></ol>
|
|
40
|
+
<ol><a href="#Ninth_Step,_Prettify">Ninth Step, Prettify</a></ol>
|
|
41
|
+
<ol><a href="#Tenth_Step,_Configuration">Tenth Step, Configuration</a></ol>
|
|
42
|
+
<ol><a href="#Eleventh_Step,_Refactor_with_AspectHelper">Eleventh Step, Refactor with AspectHelper</a></ol>
|
|
43
|
+
<ol><a href="#Twelfth_Step,_Validation_and_Errors">Twelfth Step, Validation and Errors</a></ol>
|
|
44
|
+
</li>
|
|
45
|
+
</div>
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
<a name="Step_Zero,_Introduction"><h2>Step Zero, Introduction</h2></a>
|
|
26
49
|
|
|
27
50
|
<p>Welcome to our official tutorial, the mandatory to-do list.
|
|
28
51
|
I'm writing this while doing the steps to assure it will work for you.</p>
|
|
@@ -44,10 +67,15 @@ drop by on IRC ( irc.freenode.org channel: #ramaze ).</p>
|
|
|
44
67
|
what is going on with little effort, it is also located on the project-page at
|
|
45
68
|
RubyForge.</p>
|
|
46
69
|
|
|
70
|
+
<p>Additionally, we now have added tests for the resulting application that you
|
|
71
|
+
can find in spec/examples/todolist.rb</p>
|
|
72
|
+
|
|
73
|
+
<p>Date of last update: Thu May 24 20:53:49 JST 2007</p>
|
|
74
|
+
|
|
47
75
|
<p>Thanks in advance.
|
|
48
76
|
The author of the tutorial, Michael 'manveru' Fellinger</p>
|
|
49
77
|
|
|
50
|
-
<h2>First Step, Create</h2>
|
|
78
|
+
<a name="First_Step,_Create"><h2>First Step, Create</h2></a>
|
|
51
79
|
|
|
52
80
|
<p>We are using <code>ramaze --create todolist</code> to create a new application.
|
|
53
81
|
Ramaze will then create the directory and fill it with a skeleton of a quite
|
|
@@ -61,21 +89,13 @@ to-do list.</p>
|
|
|
61
89
|
|
|
62
90
|
<p>done.</p>
|
|
63
91
|
|
|
64
|
-
<h2>Second Step, M, like Model</h2>
|
|
92
|
+
<a name="Second_Step,_M,_like_Model"><h2>Second Step, M, like Model</h2></a>
|
|
65
93
|
|
|
66
94
|
<p>Ramaze comes at the moment only with a simple wrapper of the YAML::Store.
|
|
67
95
|
So we are going to base this on the tools available, you can just do the same
|
|
68
|
-
with your ORM or database of choice.</p>
|
|
69
|
-
|
|
70
|
-
<p>So first, edit the <code>src/model.rb</code>, it is filled with the definition of a simple
|
|
71
|
-
YAML::Store already, so we are just gonna modify it a bit to use our wrapper.</p>
|
|
72
|
-
|
|
73
|
-
<p>Instead of 'yaml/store' use:</p>
|
|
96
|
+
with your ORM or database-library of choice.</p>
|
|
74
97
|
|
|
75
|
-
<
|
|
76
|
-
</code></pre>
|
|
77
|
-
|
|
78
|
-
<p>And further:</p>
|
|
98
|
+
<p>So first, edit the <code>src/model.rb</code> to fit better into our application:</p>
|
|
79
99
|
|
|
80
100
|
<pre><code>TodoList = Store::Default.new 'todolist.yaml'
|
|
81
101
|
</code></pre>
|
|
@@ -86,12 +106,12 @@ YAML::Store already, so we are just gonna modify it a bit to use our wrapper.</p
|
|
|
86
106
|
'Laundry' => {:done => false},
|
|
87
107
|
'Wash dishes' => {:done => false},
|
|
88
108
|
|
|
89
|
-
}.each do |title,
|
|
90
|
-
TodoList[title] =
|
|
109
|
+
}.each do |title, value|
|
|
110
|
+
TodoList[title] = value
|
|
91
111
|
end
|
|
92
112
|
</code></pre>
|
|
93
113
|
|
|
94
|
-
<h2>Third Step, V, like View</h2>
|
|
114
|
+
<a name="Third_Step,_V,_like_View"><h2>Third Step, V, like View</h2></a>
|
|
95
115
|
|
|
96
116
|
<p>Now let's get our hands dirty and just edit the templates for our to-do list.</p>
|
|
97
117
|
|
|
@@ -109,8 +129,8 @@ simple.</p>
|
|
|
109
129
|
<h1>TodoList</h1>
|
|
110
130
|
<ul>
|
|
111
131
|
<?r
|
|
112
|
-
TodoList.each do |title,
|
|
113
|
-
status =
|
|
132
|
+
TodoList.each do |title, value|
|
|
133
|
+
status = value[:done] ? 'done' : 'not done'
|
|
114
134
|
?>
|
|
115
135
|
<li>#{title}: #{status}</li>
|
|
116
136
|
<?r end ?>
|
|
@@ -122,10 +142,10 @@ simple.</p>
|
|
|
122
142
|
<p>I will assume that you are familiar with basic Ruby already, so let's
|
|
123
143
|
concentrate on the things new here.</p>
|
|
124
144
|
|
|
125
|
-
<p
|
|
145
|
+
<p><code><?r ?></code> defines an area of ruby-code. Late when the template is transformed into
|
|
126
146
|
pure Ruby it will be evaluated. We iterate over the TodoList model and pass the
|
|
127
|
-
title and
|
|
128
|
-
of title and status (which we define based on the
|
|
147
|
+
title and value into a block. In that block we can just get the values
|
|
148
|
+
of title and status (which we define based on the value) displayed on the
|
|
129
149
|
page.</p>
|
|
130
150
|
|
|
131
151
|
<p>The whole Template would expand to something like this (only showing the
|
|
@@ -151,7 +171,7 @@ now access it by browsing to http://localhost:7000/</p>
|
|
|
151
171
|
<code>ramaze -p 7070</code> or similar. Also be sure to look at the output of
|
|
152
172
|
<code>ramaze --help</code> to see some other options.</p>
|
|
153
173
|
|
|
154
|
-
<h2>Fourth Step, C, like Controller</h2>
|
|
174
|
+
<a name="Fourth_Step,_C,_like_Controller"><h2>Fourth Step, C, like Controller</h2></a>
|
|
155
175
|
|
|
156
176
|
<p>The last part of the MVC-paradigm is the Controller.</p>
|
|
157
177
|
|
|
@@ -162,7 +182,7 @@ Editing the model every time would be quite tiresome and limited.</p>
|
|
|
162
182
|
|
|
163
183
|
<p>In the way MVC is structured, the Controller provides the data in a nice way
|
|
164
184
|
for the View, removing all of the data-preparation and most of the logic from
|
|
165
|
-
the templates. This makes it firstly simple to change the
|
|
185
|
+
the templates. This makes it firstly simple to change the front end of your
|
|
166
186
|
application and secondly provides excellent ways of changing the complete
|
|
167
187
|
Structure of the Model or View independent from each other.</p>
|
|
168
188
|
|
|
@@ -178,17 +198,17 @@ edit the file <code>src/controller/main.rb</code>.</p>
|
|
|
178
198
|
end
|
|
179
199
|
</code></pre>
|
|
180
200
|
|
|
181
|
-
<p>The only method right now is
|
|
201
|
+
<p>The only method right now is <code>#index</code>, with a simple and for the moment quite
|
|
182
202
|
useless "Hello, World". The relationship between the methods on the controller
|
|
183
|
-
and the templates is 1:1, so the method
|
|
203
|
+
and the templates is 1:1, so the method <code>#index</code> is combined with the template
|
|
184
204
|
<code>index.xhtml</code>. This combination is called an <code>action</code>.</p>
|
|
185
205
|
|
|
186
206
|
<p>Let's get back to editing and change the index-method to this:</p>
|
|
187
207
|
|
|
188
208
|
<pre><code>def index
|
|
189
209
|
@tasks = TodoList.content
|
|
190
|
-
@tasks.each do |title,
|
|
191
|
-
status =
|
|
210
|
+
@tasks.each do |title, value|
|
|
211
|
+
status = value[:done] ? 'done' : 'not done'
|
|
192
212
|
@tasks[title] = status
|
|
193
213
|
end
|
|
194
214
|
end
|
|
@@ -203,7 +223,6 @@ changed to do following:</p>
|
|
|
203
223
|
</head>
|
|
204
224
|
<body>
|
|
205
225
|
<h1>TodoList</h1>
|
|
206
|
-
<a href="/new">New Task</a>
|
|
207
226
|
<?r if @tasks.empty? ?>
|
|
208
227
|
No Tasks
|
|
209
228
|
<?r else ?>
|
|
@@ -230,7 +249,7 @@ Tasks it will say so.</p>
|
|
|
230
249
|
<li>The return-value of the Controller does not matter (in this case).</li>
|
|
231
250
|
</ul>
|
|
232
251
|
|
|
233
|
-
<h2>Fifth Step, getting dynamic</h2>
|
|
252
|
+
<a name="Fifth_Step,_getting_dynamic"><h2>Fifth Step, getting dynamic</h2></a>
|
|
234
253
|
|
|
235
254
|
<p>We set out to build the ultimate to-do list, but there are still some things
|
|
236
255
|
missing. First off, we want to add new tasks, so let's get that done.</p>
|
|
@@ -252,7 +271,7 @@ missing. First off, we want to add new tasks, so let's get that done.</p>
|
|
|
252
271
|
<a href="/">Back to TodoList</a>
|
|
253
272
|
<form method="POST" action="create">
|
|
254
273
|
Task: <input type="text" name="title" /><br />
|
|
255
|
-
<
|
|
274
|
+
<input type="submit" />
|
|
256
275
|
</form>
|
|
257
276
|
</body>
|
|
258
277
|
</html>
|
|
@@ -274,25 +293,25 @@ moment, the request and response and the contents of the session. This is very
|
|
|
274
293
|
useful for debugging and development, you can provide your own set of
|
|
275
294
|
error-pages before going into production (or deactivate them fully) though.</p>
|
|
276
295
|
|
|
277
|
-
<p>OK, let's implement the action for
|
|
296
|
+
<p>OK, let's implement the action for <code>#create</code>, all we want to do is take the
|
|
278
297
|
requests parameters and create a new task for it, this looks like following on
|
|
279
298
|
your MainController.</p>
|
|
280
299
|
|
|
281
300
|
<pre><code>def create
|
|
282
301
|
title = request['title']
|
|
283
302
|
TodoList[title] = {:done => false}
|
|
284
|
-
redirect
|
|
303
|
+
redirect Rs()
|
|
285
304
|
end
|
|
286
305
|
</code></pre>
|
|
287
306
|
|
|
288
307
|
<p>That's all folks!</p>
|
|
289
308
|
|
|
290
|
-
<p>
|
|
309
|
+
<p>We get the title from the request-object, put it into our TodoList as undone
|
|
291
310
|
and redirect back to the mapping of the current Controller ('/' in this case).</p>
|
|
292
311
|
|
|
293
312
|
<p>Now you can create as many tasks as you want, please don't get overworked ;)</p>
|
|
294
313
|
|
|
295
|
-
<h2>Sixth Step, open and close tasks</h2>
|
|
314
|
+
<a name="Sixth_Step,_open_and_close_tasks"><h2>Sixth Step, open and close tasks</h2></a>
|
|
296
315
|
|
|
297
316
|
<p>Since the nature of tasks is to be done eventually
|
|
298
317
|
we will need some way to mark it as done or open tasks again.</p>
|
|
@@ -301,7 +320,7 @@ we will need some way to mark it as done or open tasks again.</p>
|
|
|
301
320
|
|
|
302
321
|
<pre><code><?r @tasks.each do |title, status, toggle| ?>
|
|
303
322
|
<li>
|
|
304
|
-
#{title}: #{status} - #{toggle}
|
|
323
|
+
#{title}: #{status} - [ #{toggle} ]
|
|
305
324
|
</li>
|
|
306
325
|
<?r end ?>
|
|
307
326
|
</code></pre>
|
|
@@ -312,13 +331,13 @@ we go and change the index method on the controller once again:</p>
|
|
|
312
331
|
|
|
313
332
|
<pre><code>def index
|
|
314
333
|
@tasks = []
|
|
315
|
-
TodoList.original.each do |title,
|
|
316
|
-
if
|
|
334
|
+
TodoList.original.each do |title, value|
|
|
335
|
+
if value[:done]
|
|
317
336
|
status = 'done'
|
|
318
|
-
toggle =
|
|
337
|
+
toggle = A('Open Task', :href => Rs(:open, title))
|
|
319
338
|
else
|
|
320
339
|
status = 'not done'
|
|
321
|
-
toggle =
|
|
340
|
+
toggle = A('Close Task', :href => Rs(:close, title))
|
|
322
341
|
end
|
|
323
342
|
@tasks << [title, status, toggle]
|
|
324
343
|
end
|
|
@@ -329,13 +348,13 @@ end
|
|
|
329
348
|
<p>Wow, quite some new stuff here. Let me explain that in detail.</p>
|
|
330
349
|
|
|
331
350
|
<p>We first decide whether a task is done or not, then go on and provide a link to
|
|
332
|
-
toggle the status,
|
|
333
|
-
|
|
351
|
+
toggle the status, A and Rs are both methods that help you do that.
|
|
352
|
+
The result will be something like:</p>
|
|
334
353
|
|
|
335
354
|
<pre><code><a href="/open/Wash+dishes">Close Task</a>
|
|
336
355
|
</code></pre>
|
|
337
356
|
|
|
338
|
-
<p>
|
|
357
|
+
<p>Rs actually is responsible to build the links href, for more information please
|
|
339
358
|
take a look at the RDoc for LinkHelper.</p>
|
|
340
359
|
|
|
341
360
|
<p>Also, you might have noticed that the tasks were changing order on every reload,
|
|
@@ -358,12 +377,12 @@ corresponding methods to the Controller:</p>
|
|
|
358
377
|
|
|
359
378
|
<pre><code>def open title
|
|
360
379
|
task_status title, false
|
|
361
|
-
redirect
|
|
380
|
+
redirect Rs()
|
|
362
381
|
end
|
|
363
382
|
|
|
364
383
|
def close title
|
|
365
384
|
task_status title, true
|
|
366
|
-
redirect
|
|
385
|
+
redirect Rs()
|
|
367
386
|
end
|
|
368
387
|
|
|
369
388
|
private
|
|
@@ -376,9 +395,9 @@ end
|
|
|
376
395
|
</code></pre>
|
|
377
396
|
|
|
378
397
|
<p>Oh, now what have we got here?
|
|
379
|
-
private declares that methods from here on are only to be used within the
|
|
380
|
-
Controller itself, we define an
|
|
381
|
-
status to be set so we don't have to repeat that code in <
|
|
398
|
+
<code>private</code> declares that methods from here on are only to be used within the
|
|
399
|
+
Controller itself, we define an <code>#task_status</code> method that takes the title and
|
|
400
|
+
status to be set so we don't have to repeat that code in <code>#open</code> and <code>#close</code>
|
|
382
401
|
and follow the DRY (Don't repeat yourself) paradigm.</p>
|
|
383
402
|
|
|
384
403
|
<p>Another thing we have not encountered so far is that you can define your public
|
|
@@ -392,11 +411,11 @@ methods to take parameters on their own, they will be calculated from requests.<
|
|
|
392
411
|
<pre><code>open('Wash dishes')
|
|
393
412
|
</code></pre>
|
|
394
413
|
|
|
395
|
-
<p>Which in turn will call task_status('Wash dishes', false)</p>
|
|
414
|
+
<p>Which in turn will call <code>task_status('Wash dishes', false)</code></p>
|
|
396
415
|
|
|
397
416
|
<p>That's it, go on and try it :)</p>
|
|
398
417
|
|
|
399
|
-
<h2>Seventh Step, delete tasks</h2>
|
|
418
|
+
<a name="Seventh_Step,_delete_tasks"><h2>Seventh Step, delete tasks</h2></a>
|
|
400
419
|
|
|
401
420
|
<p>Well, creating, opening and closing work now, one of the things you will
|
|
402
421
|
consider is to delete a task permanently.</p>
|
|
@@ -404,7 +423,7 @@ consider is to delete a task permanently.</p>
|
|
|
404
423
|
<p>This is just two little changes away, so let's add the link for deletion in our
|
|
405
424
|
Controller:</p>
|
|
406
425
|
|
|
407
|
-
<pre><code>delete =
|
|
426
|
+
<pre><code>delete = A('Delete', :href => Rs(:delete, title))
|
|
408
427
|
@tasks << [title, status, toggle, delete]
|
|
409
428
|
</code></pre>
|
|
410
429
|
|
|
@@ -412,7 +431,7 @@ Controller:</p>
|
|
|
412
431
|
|
|
413
432
|
<pre><code>def delete title
|
|
414
433
|
TodoList.delete title
|
|
415
|
-
redirect
|
|
434
|
+
redirect Rs()
|
|
416
435
|
end
|
|
417
436
|
</code></pre>
|
|
418
437
|
|
|
@@ -431,13 +450,13 @@ section will contact you within the next few days.</p>
|
|
|
431
450
|
<p>Just kidding, but that really are the basics, in the next few steps I will
|
|
432
451
|
explain some more advanced concepts of Ramaze and the templating.</p>
|
|
433
452
|
|
|
434
|
-
<h2>Eighth Step, Elements</h2>
|
|
453
|
+
<a name="Eighth_Step,_Elements"><h2>Eighth Step, Elements</h2></a>
|
|
435
454
|
|
|
436
455
|
<pre><code><Page></Page>
|
|
437
456
|
</code></pre>
|
|
438
457
|
|
|
439
458
|
<p>This is called an Element, Ramaze will go and search for a class that matches
|
|
440
|
-
the name Page and responds to <
|
|
459
|
+
the name Page and responds to <code>#render</code>. Then it will go and hand the content in
|
|
441
460
|
between to that Element.</p>
|
|
442
461
|
|
|
443
462
|
<p>Sounds weird?</p>
|
|
@@ -468,7 +487,7 @@ awful lot of sense to change the enclosing stuff in one place.</p>
|
|
|
468
487
|
|
|
469
488
|
<p>Take a look at the <code>src/element/page.rb</code></p>
|
|
470
489
|
|
|
471
|
-
<pre><code>class Page < Element
|
|
490
|
+
<pre><code>class Page < Ezamar::Element
|
|
472
491
|
def render
|
|
473
492
|
%{
|
|
474
493
|
<html>
|
|
@@ -485,13 +504,13 @@ end
|
|
|
485
504
|
</code></pre>
|
|
486
505
|
|
|
487
506
|
<p>Alright, most things we need are in place already, the most important thing
|
|
488
|
-
is the <
|
|
489
|
-
<
|
|
507
|
+
is the <code>#content</code> method that we call with <code>#{content}</code> inside the string in
|
|
508
|
+
<code>#render</code>.</p>
|
|
490
509
|
|
|
491
510
|
<p>Just adopt it to your liking, I'll just use the things we had in our templates
|
|
492
511
|
so far:</p>
|
|
493
512
|
|
|
494
|
-
<pre><code>class Page < Element
|
|
513
|
+
<pre><code>class Page < Ezamar::Element
|
|
495
514
|
def render
|
|
496
515
|
%{
|
|
497
516
|
<html>
|
|
@@ -499,7 +518,7 @@ so far:</p>
|
|
|
499
518
|
<title>TodoList</title>
|
|
500
519
|
</head>
|
|
501
520
|
<body>
|
|
502
|
-
<h1>#{@
|
|
521
|
+
<h1>#{@title}</h1>
|
|
503
522
|
#{content}
|
|
504
523
|
</body>
|
|
505
524
|
</html>
|
|
@@ -508,8 +527,7 @@ so far:</p>
|
|
|
508
527
|
end
|
|
509
528
|
</code></pre>
|
|
510
529
|
|
|
511
|
-
<p>Please note that
|
|
512
|
-
to tye Page-tag.</p>
|
|
530
|
+
<p>Please note that instance variables reflecting the parameters are set.</p>
|
|
513
531
|
|
|
514
532
|
<p>And let's change our templates as well.</p>
|
|
515
533
|
|
|
@@ -545,9 +563,10 @@ to tye Page-tag.</p>
|
|
|
545
563
|
<p>Alright, now just go and look at the result in the browser, try changing
|
|
546
564
|
the things inside the Element and look at how it behaves.</p>
|
|
547
565
|
|
|
548
|
-
<h2>Ninth Step, Prettify</h2>
|
|
566
|
+
<a name="Ninth_Step,_Prettify"><h2>Ninth Step, Prettify</h2></a>
|
|
549
567
|
|
|
550
|
-
<p>Let's structure the data inside the list a little bit, in this case into a table
|
|
568
|
+
<p>Let's structure the data inside the list a little bit, in this case into a table
|
|
569
|
+
to get it line up properly and look actually structured.</p>
|
|
551
570
|
|
|
552
571
|
<p>So, from what we have right now:</p>
|
|
553
572
|
|
|
@@ -574,7 +593,8 @@ the things inside the Element and look at how it behaves.</p>
|
|
|
574
593
|
</table>
|
|
575
594
|
</code></pre>
|
|
576
595
|
|
|
577
|
-
<p>And, since we have proper classes to address some style sheets, jump into the
|
|
596
|
+
<p>And, since we have proper classes to address some style sheets, jump into the
|
|
597
|
+
Page element and add some style sheet like that:</p>
|
|
578
598
|
|
|
579
599
|
<pre><code><head>
|
|
580
600
|
<title>TodoList</title>
|
|
@@ -589,11 +609,219 @@ the things inside the Element and look at how it behaves.</p>
|
|
|
589
609
|
</head>
|
|
590
610
|
</code></pre>
|
|
591
611
|
|
|
592
|
-
<p>That looks quite a bit nicer, right?
|
|
593
|
-
|
|
612
|
+
<p>That looks quite a bit nicer, right? And yes, if you don't like tables (though
|
|
613
|
+
this is an entirely legit use in my opinion, you can just do it like you want,
|
|
614
|
+
using nested lists or divs/spans, replacing the open/close and delete links with
|
|
615
|
+
nice images and changing the style according to the status.</p>
|
|
594
616
|
|
|
595
617
|
<p>I will leave this as an exercise to the reader.</p>
|
|
596
618
|
|
|
619
|
+
<a name="Tenth_Step,_Configuration"><h2>Tenth Step, Configuration</h2></a>
|
|
620
|
+
|
|
621
|
+
<p>To round up this tutorial a bit, let's introduce you to configuration in Ramaze.
|
|
622
|
+
This will not go into full depth of possibilities or a total coverage of the
|
|
623
|
+
options, since they are bound to change over time.</p>
|
|
624
|
+
|
|
625
|
+
<p>First of all, the default port Ramaze runs on is 7000, but to make it a usual
|
|
626
|
+
webserver it has to run on port 80. So, let's add following line in your
|
|
627
|
+
main.rb right after the lines of require you added before:</p>
|
|
628
|
+
|
|
629
|
+
<pre><code>Ramaze::Global.port = 80
|
|
630
|
+
</code></pre>
|
|
631
|
+
|
|
632
|
+
<p>Alright, that wasn't that hard.
|
|
633
|
+
Let's say now you also want to run Mongrel instead of WEBrick, to get nice a bit
|
|
634
|
+
of performance:</p>
|
|
635
|
+
|
|
636
|
+
<pre><code>Ramaze::Global.adapter = :mongrel
|
|
637
|
+
</code></pre>
|
|
638
|
+
|
|
639
|
+
<p>To do this in a DRY way you could also do following:</p>
|
|
640
|
+
|
|
641
|
+
<pre><code>Ramaze::Global.setup do |g|
|
|
642
|
+
g.port = 80
|
|
643
|
+
g.adapter = :mongrel
|
|
644
|
+
end
|
|
645
|
+
</code></pre>
|
|
646
|
+
|
|
647
|
+
<p>It seems to be quite common to put this configuration into separate files so you
|
|
648
|
+
can just require it on demand. There are other, slightly stronger way to set
|
|
649
|
+
options, which is either using flags on the ramaze executable, or like this:</p>
|
|
650
|
+
|
|
651
|
+
<pre><code>Ramaze.start :port => 80, :adapter => :mongrel
|
|
652
|
+
</code></pre>
|
|
653
|
+
|
|
654
|
+
<p>We haven't started Ramaze directly as of yet, but this allows you to ignore the
|
|
655
|
+
ramaze executable and just run your application.</p>
|
|
656
|
+
|
|
657
|
+
<a name="Eleventh_Step,_Refactor_with_AspectHelper"><h2>Eleventh Step, Refactor with AspectHelper</h2></a>
|
|
658
|
+
|
|
659
|
+
<p>Now, if you take a closer look at the Controller you will see:</p>
|
|
660
|
+
|
|
661
|
+
<pre><code>def create
|
|
662
|
+
title = request['title']
|
|
663
|
+
TodoList[title] = {:done => false}
|
|
664
|
+
redirect R(self)
|
|
665
|
+
end
|
|
666
|
+
|
|
667
|
+
def open title
|
|
668
|
+
task_status title, false
|
|
669
|
+
redirect R(self)
|
|
670
|
+
end
|
|
671
|
+
|
|
672
|
+
def close title
|
|
673
|
+
task_status title, true
|
|
674
|
+
redirect R(self)
|
|
675
|
+
end
|
|
676
|
+
|
|
677
|
+
def delete title
|
|
678
|
+
TodoList.delete title
|
|
679
|
+
redirect R(self)
|
|
680
|
+
end
|
|
681
|
+
</code></pre>
|
|
682
|
+
|
|
683
|
+
<p>We did some refactoring before, by introducing <code>#task_status</code>, but here we have
|
|
684
|
+
repetition again: <code>redirect Rs()</code> <em>after</em> each method did its job.</p>
|
|
685
|
+
|
|
686
|
+
<p>However, we can take advantage of one of the helpers Ramaze offers, the
|
|
687
|
+
AspectHelper.
|
|
688
|
+
It allows you to easily wrap actions in your controller with other methods</p>
|
|
689
|
+
|
|
690
|
+
<p>In your Controller, replace the previous chunk with following:</p>
|
|
691
|
+
|
|
692
|
+
<pre><code>def create
|
|
693
|
+
title = request['title']
|
|
694
|
+
TodoList[title] = {:done => false}
|
|
695
|
+
end
|
|
696
|
+
|
|
697
|
+
def open title
|
|
698
|
+
task_status title, false
|
|
699
|
+
end
|
|
700
|
+
|
|
701
|
+
def close title
|
|
702
|
+
task_status title, true
|
|
703
|
+
end
|
|
704
|
+
|
|
705
|
+
def delete title
|
|
706
|
+
TodoList.delete title
|
|
707
|
+
end
|
|
708
|
+
|
|
709
|
+
helper :aspect
|
|
710
|
+
after(:create, :open, :close, :delete){ redirect_index }
|
|
711
|
+
|
|
712
|
+
def redirect_index
|
|
713
|
+
redirect Rs()
|
|
714
|
+
end
|
|
715
|
+
</code></pre>
|
|
716
|
+
|
|
717
|
+
<p>Alright, that looks a lot nicer already and is definitely easier to maintain.
|
|
718
|
+
Please note that the <code>#redirect_index</code> method should not be private, as it is a
|
|
719
|
+
usual action that will just run after the others.</p>
|
|
720
|
+
|
|
721
|
+
<p>There is a symmetrical <code>#before</code> aspect that you could take advantage of as well,
|
|
722
|
+
and in case you want to add required authentication for all actions of a
|
|
723
|
+
Controller you could use <code>#before_all</code> instead of a list of action-names.</p>
|
|
724
|
+
|
|
725
|
+
<a name="Twelfth_Step,_Validation_and_Errors"><h2>Twelfth Step, Validation and Errors</h2></a>
|
|
726
|
+
|
|
727
|
+
<p>Right now, all kinds of things could still go wrong when you do things like
|
|
728
|
+
creating tasks with no title at all or try to open/close a task that does not
|
|
729
|
+
exist. So in this step we will add some little checks for these cases.</p>
|
|
730
|
+
|
|
731
|
+
<p>First we head over to the Controller again and take a look at <code>#create</code>:</p>
|
|
732
|
+
|
|
733
|
+
<pre><code>def create
|
|
734
|
+
title = request['title']
|
|
735
|
+
TodoList[title] = {:done => false}
|
|
736
|
+
end
|
|
737
|
+
</code></pre>
|
|
738
|
+
|
|
739
|
+
<p>Here we just create a new task, no matter what we get. Every seasoned
|
|
740
|
+
web-developer would advise you to be suspicious about all the input you receive
|
|
741
|
+
from your users, so let's apply this advice.</p>
|
|
742
|
+
|
|
743
|
+
<pre><code>def create
|
|
744
|
+
if title = request['title']
|
|
745
|
+
title.strip!
|
|
746
|
+
if title.empty?
|
|
747
|
+
error("Please enter a title")
|
|
748
|
+
redirect '/new'
|
|
749
|
+
end
|
|
750
|
+
TodoList[title] = {:done => false}
|
|
751
|
+
end
|
|
752
|
+
end
|
|
753
|
+
</code></pre>
|
|
754
|
+
|
|
755
|
+
<p>First of all we check if we got a request with a value for 'title', if we get
|
|
756
|
+
none we just let the aspect kick in that will redirect the browser to the index.
|
|
757
|
+
Next we strip the title of all spaces around it so we can check if it is empty.
|
|
758
|
+
We will talk about the specifics of our error-handling now.</p>
|
|
759
|
+
|
|
760
|
+
<p>Ramaze has a helper called FlashHelper, that will keep a hash associated with
|
|
761
|
+
the session for one request, afterwards the hash is thrown away. This is
|
|
762
|
+
specifically useful for giving the user feedback while keeping a stateless
|
|
763
|
+
approach.</p>
|
|
764
|
+
|
|
765
|
+
<p>Let me show you our <code>#error</code> method (it goes in the private section to
|
|
766
|
+
<code>#task_status</code>):</p>
|
|
767
|
+
|
|
768
|
+
<pre><code>def error(message)
|
|
769
|
+
flash[:error] = message
|
|
770
|
+
end
|
|
771
|
+
</code></pre>
|
|
772
|
+
|
|
773
|
+
<p>Duh, you may say, wouldn't that fit in the one line instead of the call to
|
|
774
|
+
<code>#error</code>?
|
|
775
|
+
Indeed, it would, but let me remind you, we have no checks for changing the
|
|
776
|
+
status of a task yet. We will need error-handling there as well, so we just keep
|
|
777
|
+
our code DRY and maintainable by collecting shared behaviour in small pieces.</p>
|
|
778
|
+
|
|
779
|
+
<p>Now on to the <code>#task_status</code>:</p>
|
|
780
|
+
|
|
781
|
+
<pre><code>def task_status title, status
|
|
782
|
+
unless task = TodoList[title]
|
|
783
|
+
error "No such Task: `#{title}'"
|
|
784
|
+
redirect_referer
|
|
785
|
+
end
|
|
786
|
+
|
|
787
|
+
task[:done] = status
|
|
788
|
+
TodoList[title] = task
|
|
789
|
+
end
|
|
790
|
+
</code></pre>
|
|
791
|
+
|
|
792
|
+
<p>That used to look like this:</p>
|
|
793
|
+
|
|
794
|
+
<pre><code>def task_status title, status
|
|
795
|
+
task = TodoList[title]
|
|
796
|
+
task[:done] = status
|
|
797
|
+
TodoList[title] = task
|
|
798
|
+
end
|
|
799
|
+
</code></pre>
|
|
800
|
+
|
|
801
|
+
<p>So in fact all we added is a check whether a task already exists, set an
|
|
802
|
+
error-message in case it doesn't and redirect to wherever the browser came from.</p>
|
|
803
|
+
|
|
804
|
+
<p>But what about actually showing the error-messages we so carefully set? Well,
|
|
805
|
+
where do we change the view? Right, in the templates. But both templates we have
|
|
806
|
+
so far (index and new) share this behaviour, so let's head over to the Element
|
|
807
|
+
and add in the right place:</p>
|
|
808
|
+
|
|
809
|
+
<pre><code><body>
|
|
810
|
+
<h1>#{@title}</h1>
|
|
811
|
+
<?r if flash[:error] ?>
|
|
812
|
+
<div class="error">
|
|
813
|
+
\#{flash[:error]}
|
|
814
|
+
</div>
|
|
815
|
+
<?r end ?>
|
|
816
|
+
#{content}
|
|
817
|
+
</body>
|
|
818
|
+
</code></pre>
|
|
819
|
+
|
|
820
|
+
<p>The only thing special about it is the <code>\#{flash[:error]}</code>, we have to escape
|
|
821
|
+
the <code>#</code> so it won't evaluate this immediately but wait until it is really
|
|
822
|
+
rendered.
|
|
823
|
+
You can add some nifty style if you like.</p>
|
|
824
|
+
|
|
597
825
|
<p>To be continued...</p>
|
|
598
826
|
</body>
|
|
599
827
|
</html>
|