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
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# To-do List Tutorial
|
|
2
2
|
|
|
3
|
+
## Step Zero, Introduction
|
|
4
|
+
|
|
3
5
|
Welcome to our official tutorial, the mandatory to-do list.
|
|
4
6
|
I'm writing this while doing the steps to assure it will work for you.
|
|
5
7
|
|
|
@@ -20,6 +22,11 @@ There is also a Mailing list available where you can keep yourself updated on
|
|
|
20
22
|
what is going on with little effort, it is also located on the project-page at
|
|
21
23
|
RubyForge.
|
|
22
24
|
|
|
25
|
+
Additionally, we now have added tests for the resulting application that you
|
|
26
|
+
can find in spec/examples/todolist.rb
|
|
27
|
+
|
|
28
|
+
Date of last update: Thu May 24 20:53:49 JST 2007
|
|
29
|
+
|
|
23
30
|
Thanks in advance.
|
|
24
31
|
The author of the tutorial, Michael 'manveru' Fellinger
|
|
25
32
|
|
|
@@ -41,16 +48,9 @@ done.
|
|
|
41
48
|
|
|
42
49
|
Ramaze comes at the moment only with a simple wrapper of the YAML::Store.
|
|
43
50
|
So we are going to base this on the tools available, you can just do the same
|
|
44
|
-
with your ORM or database of choice.
|
|
45
|
-
|
|
46
|
-
So first, edit the `src/model.rb`, it is filled with the definition of a simple
|
|
47
|
-
YAML::Store already, so we are just gonna modify it a bit to use our wrapper.
|
|
51
|
+
with your ORM or database-library of choice.
|
|
48
52
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
require 'ramaze/store/default'
|
|
52
|
-
|
|
53
|
-
And further:
|
|
53
|
+
So first, edit the `src/model.rb` to fit better into our application:
|
|
54
54
|
|
|
55
55
|
TodoList = Store::Default.new 'todolist.yaml'
|
|
56
56
|
|
|
@@ -60,8 +60,8 @@ To have a base to start off of, let's add some items as well.
|
|
|
60
60
|
'Laundry' => {:done => false},
|
|
61
61
|
'Wash dishes' => {:done => false},
|
|
62
62
|
|
|
63
|
-
}.each do |title,
|
|
64
|
-
TodoList[title] =
|
|
63
|
+
}.each do |title, value|
|
|
64
|
+
TodoList[title] = value
|
|
65
65
|
end
|
|
66
66
|
|
|
67
67
|
|
|
@@ -83,8 +83,8 @@ simple.
|
|
|
83
83
|
<h1>TodoList</h1>
|
|
84
84
|
<ul>
|
|
85
85
|
<?r
|
|
86
|
-
TodoList.each do |title,
|
|
87
|
-
status =
|
|
86
|
+
TodoList.each do |title, value|
|
|
87
|
+
status = value[:done] ? 'done' : 'not done'
|
|
88
88
|
?>
|
|
89
89
|
<li>#{title}: #{status}</li>
|
|
90
90
|
<?r end ?>
|
|
@@ -95,10 +95,10 @@ simple.
|
|
|
95
95
|
I will assume that you are familiar with basic Ruby already, so let's
|
|
96
96
|
concentrate on the things new here.
|
|
97
97
|
|
|
98
|
-
|
|
98
|
+
`<?r ?>` defines an area of ruby-code. Late when the template is transformed into
|
|
99
99
|
pure Ruby it will be evaluated. We iterate over the TodoList model and pass the
|
|
100
|
-
title and
|
|
101
|
-
of title and status (which we define based on the
|
|
100
|
+
title and value into a block. In that block we can just get the values
|
|
101
|
+
of title and status (which we define based on the value) displayed on the
|
|
102
102
|
page.
|
|
103
103
|
|
|
104
104
|
The whole Template would expand to something like this (only showing the
|
|
@@ -135,7 +135,7 @@ Well, come along, I'll introduce you to Controller.
|
|
|
135
135
|
|
|
136
136
|
In the way MVC is structured, the Controller provides the data in a nice way
|
|
137
137
|
for the View, removing all of the data-preparation and most of the logic from
|
|
138
|
-
the templates. This makes it firstly simple to change the
|
|
138
|
+
the templates. This makes it firstly simple to change the front end of your
|
|
139
139
|
application and secondly provides excellent ways of changing the complete
|
|
140
140
|
Structure of the Model or View independent from each other.
|
|
141
141
|
|
|
@@ -150,17 +150,17 @@ The contents of it are like following:
|
|
|
150
150
|
end
|
|
151
151
|
end
|
|
152
152
|
|
|
153
|
-
The only method right now is
|
|
153
|
+
The only method right now is `#index`, with a simple and for the moment quite
|
|
154
154
|
useless "Hello, World". The relationship between the methods on the controller
|
|
155
|
-
and the templates is 1:1, so the method
|
|
155
|
+
and the templates is 1:1, so the method `#index` is combined with the template
|
|
156
156
|
`index.xhtml`. This combination is called an `action`.
|
|
157
157
|
|
|
158
158
|
Let's get back to editing and change the index-method to this:
|
|
159
159
|
|
|
160
160
|
def index
|
|
161
161
|
@tasks = TodoList.content
|
|
162
|
-
@tasks.each do |title,
|
|
163
|
-
status =
|
|
162
|
+
@tasks.each do |title, value|
|
|
163
|
+
status = value[:done] ? 'done' : 'not done'
|
|
164
164
|
@tasks[title] = status
|
|
165
165
|
end
|
|
166
166
|
end
|
|
@@ -174,7 +174,6 @@ changed to do following:
|
|
|
174
174
|
</head>
|
|
175
175
|
<body>
|
|
176
176
|
<h1>TodoList</h1>
|
|
177
|
-
<a href="/new">New Task</a>
|
|
178
177
|
<?r if @tasks.empty? ?>
|
|
179
178
|
No Tasks
|
|
180
179
|
<?r else ?>
|
|
@@ -219,7 +218,7 @@ Open a new file `template/new.xhtml` with a form to add a new task.
|
|
|
219
218
|
<a href="/">Back to TodoList</a>
|
|
220
219
|
<form method="POST" action="create">
|
|
221
220
|
Task: <input type="text" name="title" /><br />
|
|
222
|
-
<
|
|
221
|
+
<input type="submit" />
|
|
223
222
|
</form>
|
|
224
223
|
</body>
|
|
225
224
|
</html>
|
|
@@ -240,19 +239,19 @@ moment, the request and response and the contents of the session. This is very
|
|
|
240
239
|
useful for debugging and development, you can provide your own set of
|
|
241
240
|
error-pages before going into production (or deactivate them fully) though.
|
|
242
241
|
|
|
243
|
-
OK, let's implement the action for
|
|
242
|
+
OK, let's implement the action for `#create`, all we want to do is take the
|
|
244
243
|
requests parameters and create a new task for it, this looks like following on
|
|
245
244
|
your MainController.
|
|
246
245
|
|
|
247
246
|
def create
|
|
248
247
|
title = request['title']
|
|
249
248
|
TodoList[title] = {:done => false}
|
|
250
|
-
redirect
|
|
249
|
+
redirect Rs()
|
|
251
250
|
end
|
|
252
251
|
|
|
253
252
|
That's all folks!
|
|
254
253
|
|
|
255
|
-
|
|
254
|
+
We get the title from the request-object, put it into our TodoList as undone
|
|
256
255
|
and redirect back to the mapping of the current Controller ('/' in this case).
|
|
257
256
|
|
|
258
257
|
Now you can create as many tasks as you want, please don't get overworked ;)
|
|
@@ -268,7 +267,7 @@ Jump into `template/index.xhtml` and do the following:
|
|
|
268
267
|
|
|
269
268
|
<?r @tasks.each do |title, status, toggle| ?>
|
|
270
269
|
<li>
|
|
271
|
-
#{title}: #{status} - #{toggle}
|
|
270
|
+
#{title}: #{status} - [ #{toggle} ]
|
|
272
271
|
</li>
|
|
273
272
|
<?r end ?>
|
|
274
273
|
|
|
@@ -278,13 +277,13 @@ we go and change the index method on the controller once again:
|
|
|
278
277
|
|
|
279
278
|
def index
|
|
280
279
|
@tasks = []
|
|
281
|
-
TodoList.original.each do |title,
|
|
282
|
-
if
|
|
280
|
+
TodoList.original.each do |title, value|
|
|
281
|
+
if value[:done]
|
|
283
282
|
status = 'done'
|
|
284
|
-
toggle =
|
|
283
|
+
toggle = A('Open Task', :href => Rs(:open, title))
|
|
285
284
|
else
|
|
286
285
|
status = 'not done'
|
|
287
|
-
toggle =
|
|
286
|
+
toggle = A('Close Task', :href => Rs(:close, title))
|
|
288
287
|
end
|
|
289
288
|
@tasks << [title, status, toggle]
|
|
290
289
|
end
|
|
@@ -294,12 +293,12 @@ we go and change the index method on the controller once again:
|
|
|
294
293
|
Wow, quite some new stuff here. Let me explain that in detail.
|
|
295
294
|
|
|
296
295
|
We first decide whether a task is done or not, then go on and provide a link to
|
|
297
|
-
toggle the status,
|
|
298
|
-
|
|
296
|
+
toggle the status, A and Rs are both methods that help you do that.
|
|
297
|
+
The result will be something like:
|
|
299
298
|
|
|
300
299
|
<a href="/open/Wash+dishes">Close Task</a>
|
|
301
300
|
|
|
302
|
-
|
|
301
|
+
Rs actually is responsible to build the links href, for more information please
|
|
303
302
|
take a look at the RDoc for LinkHelper.
|
|
304
303
|
|
|
305
304
|
Also, you might have noticed that the tasks were changing order on every reload,
|
|
@@ -321,12 +320,12 @@ corresponding methods to the Controller:
|
|
|
321
320
|
|
|
322
321
|
def open title
|
|
323
322
|
task_status title, false
|
|
324
|
-
redirect
|
|
323
|
+
redirect Rs()
|
|
325
324
|
end
|
|
326
325
|
|
|
327
326
|
def close title
|
|
328
327
|
task_status title, true
|
|
329
|
-
redirect
|
|
328
|
+
redirect Rs()
|
|
330
329
|
end
|
|
331
330
|
|
|
332
331
|
private
|
|
@@ -338,9 +337,9 @@ corresponding methods to the Controller:
|
|
|
338
337
|
end
|
|
339
338
|
|
|
340
339
|
Oh, now what have we got here?
|
|
341
|
-
private declares that methods from here on are only to be used within the
|
|
342
|
-
Controller itself, we define an
|
|
343
|
-
status to be set so we don't have to repeat that code in
|
|
340
|
+
`private` declares that methods from here on are only to be used within the
|
|
341
|
+
Controller itself, we define an `#task_status` method that takes the title and
|
|
342
|
+
status to be set so we don't have to repeat that code in `#open` and `#close`
|
|
344
343
|
and follow the DRY (Don't repeat yourself) paradigm.
|
|
345
344
|
|
|
346
345
|
Another thing we have not encountered so far is that you can define your public
|
|
@@ -352,7 +351,7 @@ will translate into:
|
|
|
352
351
|
|
|
353
352
|
open('Wash dishes')
|
|
354
353
|
|
|
355
|
-
Which in turn will call task_status('Wash dishes', false)
|
|
354
|
+
Which in turn will call `task_status('Wash dishes', false)`
|
|
356
355
|
|
|
357
356
|
That's it, go on and try it :)
|
|
358
357
|
|
|
@@ -364,14 +363,14 @@ consider is to delete a task permanently.
|
|
|
364
363
|
This is just two little changes away, so let's add the link for deletion in our
|
|
365
364
|
Controller:
|
|
366
365
|
|
|
367
|
-
delete =
|
|
366
|
+
delete = A('Delete', :href => Rs(:delete, title))
|
|
368
367
|
@tasks << [title, status, toggle, delete]
|
|
369
368
|
|
|
370
369
|
and an corresponding method while we're at it:
|
|
371
370
|
|
|
372
371
|
def delete title
|
|
373
372
|
TodoList.delete title
|
|
374
|
-
redirect
|
|
373
|
+
redirect Rs()
|
|
375
374
|
end
|
|
376
375
|
|
|
377
376
|
Now jumping to `template/index.xhtml` again, change it so it shows the link:
|
|
@@ -394,7 +393,7 @@ explain some more advanced concepts of Ramaze and the templating.
|
|
|
394
393
|
<Page></Page>
|
|
395
394
|
|
|
396
395
|
This is called an Element, Ramaze will go and search for a class that matches
|
|
397
|
-
the name Page and responds to
|
|
396
|
+
the name Page and responds to `#render`. Then it will go and hand the content in
|
|
398
397
|
between to that Element.
|
|
399
398
|
|
|
400
399
|
Sounds weird?
|
|
@@ -423,7 +422,7 @@ So let's apply DRY here as well.
|
|
|
423
422
|
|
|
424
423
|
Take a look at the `src/element/page.rb`
|
|
425
424
|
|
|
426
|
-
class Page < Element
|
|
425
|
+
class Page < Ezamar::Element
|
|
427
426
|
def render
|
|
428
427
|
%{
|
|
429
428
|
<html>
|
|
@@ -439,13 +438,13 @@ Take a look at the `src/element/page.rb`
|
|
|
439
438
|
end
|
|
440
439
|
|
|
441
440
|
Alright, most things we need are in place already, the most important thing
|
|
442
|
-
is the
|
|
443
|
-
|
|
441
|
+
is the `#content` method that we call with `#{content}` inside the string in
|
|
442
|
+
`#render`.
|
|
444
443
|
|
|
445
444
|
Just adopt it to your liking, I'll just use the things we had in our templates
|
|
446
445
|
so far:
|
|
447
446
|
|
|
448
|
-
class Page < Element
|
|
447
|
+
class Page < Ezamar::Element
|
|
449
448
|
def render
|
|
450
449
|
%{
|
|
451
450
|
<html>
|
|
@@ -498,7 +497,8 @@ the things inside the Element and look at how it behaves.
|
|
|
498
497
|
|
|
499
498
|
## Ninth Step, Prettify
|
|
500
499
|
|
|
501
|
-
Let's structure the data inside the list a little bit, in this case into a table
|
|
500
|
+
Let's structure the data inside the list a little bit, in this case into a table
|
|
501
|
+
to get it line up properly and look actually structured.
|
|
502
502
|
|
|
503
503
|
So, from what we have right now:
|
|
504
504
|
|
|
@@ -523,7 +523,8 @@ To something like this:
|
|
|
523
523
|
<?r end ?>
|
|
524
524
|
</table>
|
|
525
525
|
|
|
526
|
-
And, since we have proper classes to address some style sheets, jump into the
|
|
526
|
+
And, since we have proper classes to address some style sheets, jump into the
|
|
527
|
+
Page element and add some style sheet like that:
|
|
527
528
|
|
|
528
529
|
<head>
|
|
529
530
|
<title>TodoList</title>
|
|
@@ -537,9 +538,208 @@ And, since we have proper classes to address some style sheets, jump into the Pa
|
|
|
537
538
|
</style>
|
|
538
539
|
</head>
|
|
539
540
|
|
|
540
|
-
That looks quite a bit nicer, right?
|
|
541
|
-
|
|
541
|
+
That looks quite a bit nicer, right? And yes, if you don't like tables (though
|
|
542
|
+
this is an entirely legit use in my opinion, you can just do it like you want,
|
|
543
|
+
using nested lists or divs/spans, replacing the open/close and delete links with
|
|
544
|
+
nice images and changing the style according to the status.
|
|
542
545
|
|
|
543
546
|
I will leave this as an exercise to the reader.
|
|
544
547
|
|
|
548
|
+
|
|
549
|
+
## Tenth Step, Configuration
|
|
550
|
+
|
|
551
|
+
To round up this tutorial a bit, let's introduce you to configuration in Ramaze.
|
|
552
|
+
This will not go into full depth of possibilities or a total coverage of the
|
|
553
|
+
options, since they are bound to change over time.
|
|
554
|
+
|
|
555
|
+
First of all, the default port Ramaze runs on is 7000, but to make it a usual
|
|
556
|
+
webserver it has to run on port 80. So, let's add following line in your
|
|
557
|
+
main.rb right after the lines of require you added before:
|
|
558
|
+
|
|
559
|
+
Ramaze::Global.port = 80
|
|
560
|
+
|
|
561
|
+
Alright, that wasn't that hard.
|
|
562
|
+
Let's say now you also want to run Mongrel instead of WEBrick, to get nice a bit
|
|
563
|
+
of performance:
|
|
564
|
+
|
|
565
|
+
Ramaze::Global.adapter = :mongrel
|
|
566
|
+
|
|
567
|
+
To do this in a DRY way you could also do following:
|
|
568
|
+
|
|
569
|
+
Ramaze::Global.setup do |g|
|
|
570
|
+
g.port = 80
|
|
571
|
+
g.adapter = :mongrel
|
|
572
|
+
end
|
|
573
|
+
|
|
574
|
+
It seems to be quite common to put this configuration into separate files so you
|
|
575
|
+
can just require it on demand. There are other, slightly stronger way to set
|
|
576
|
+
options, which is either using flags on the ramaze executable, or like this:
|
|
577
|
+
|
|
578
|
+
Ramaze.start :port => 80, :adapter => :mongrel
|
|
579
|
+
|
|
580
|
+
We haven't started Ramaze directly as of yet, but this allows you to ignore the
|
|
581
|
+
ramaze executable and just run your application.
|
|
582
|
+
|
|
583
|
+
|
|
584
|
+
## Eleventh Step, Refactor with AspectHelper
|
|
585
|
+
|
|
586
|
+
Now, if you take a closer look at the Controller you will see:
|
|
587
|
+
|
|
588
|
+
def create
|
|
589
|
+
title = request['title']
|
|
590
|
+
TodoList[title] = {:done => false}
|
|
591
|
+
redirect R(self)
|
|
592
|
+
end
|
|
593
|
+
|
|
594
|
+
def open title
|
|
595
|
+
task_status title, false
|
|
596
|
+
redirect R(self)
|
|
597
|
+
end
|
|
598
|
+
|
|
599
|
+
def close title
|
|
600
|
+
task_status title, true
|
|
601
|
+
redirect R(self)
|
|
602
|
+
end
|
|
603
|
+
|
|
604
|
+
def delete title
|
|
605
|
+
TodoList.delete title
|
|
606
|
+
redirect R(self)
|
|
607
|
+
end
|
|
608
|
+
|
|
609
|
+
We did some refactoring before, by introducing `#task_status`, but here we have
|
|
610
|
+
repetition again: `redirect Rs()` _after_ each method did its job.
|
|
611
|
+
|
|
612
|
+
However, we can take advantage of one of the helpers Ramaze offers, the
|
|
613
|
+
AspectHelper.
|
|
614
|
+
It allows you to easily wrap actions in your controller with other methods
|
|
615
|
+
|
|
616
|
+
In your Controller, replace the previous chunk with following:
|
|
617
|
+
|
|
618
|
+
def create
|
|
619
|
+
title = request['title']
|
|
620
|
+
TodoList[title] = {:done => false}
|
|
621
|
+
end
|
|
622
|
+
|
|
623
|
+
def open title
|
|
624
|
+
task_status title, false
|
|
625
|
+
end
|
|
626
|
+
|
|
627
|
+
def close title
|
|
628
|
+
task_status title, true
|
|
629
|
+
end
|
|
630
|
+
|
|
631
|
+
def delete title
|
|
632
|
+
TodoList.delete title
|
|
633
|
+
end
|
|
634
|
+
|
|
635
|
+
helper :aspect
|
|
636
|
+
after(:create, :open, :close, :delete){ redirect_index }
|
|
637
|
+
|
|
638
|
+
def redirect_index
|
|
639
|
+
redirect Rs()
|
|
640
|
+
end
|
|
641
|
+
|
|
642
|
+
Alright, that looks a lot nicer already and is definitely easier to maintain.
|
|
643
|
+
Please note that the `#redirect_index` method should not be private, as it is a
|
|
644
|
+
usual action that will just run after the others.
|
|
645
|
+
|
|
646
|
+
There is a symmetrical `#before` aspect that you could take advantage of as well,
|
|
647
|
+
and in case you want to add required authentication for all actions of a
|
|
648
|
+
Controller you could use `#before_all` instead of a list of action-names.
|
|
649
|
+
|
|
650
|
+
|
|
651
|
+
## Twelfth Step, Validation and Errors
|
|
652
|
+
|
|
653
|
+
Right now, all kinds of things could still go wrong when you do things like
|
|
654
|
+
creating tasks with no title at all or try to open/close a task that does not
|
|
655
|
+
exist. So in this step we will add some little checks for these cases.
|
|
656
|
+
|
|
657
|
+
First we head over to the Controller again and take a look at `#create`:
|
|
658
|
+
|
|
659
|
+
def create
|
|
660
|
+
title = request['title']
|
|
661
|
+
TodoList[title] = {:done => false}
|
|
662
|
+
end
|
|
663
|
+
|
|
664
|
+
Here we just create a new task, no matter what we get. Every seasoned
|
|
665
|
+
web-developer would advise you to be suspicious about all the input you receive
|
|
666
|
+
from your users, so let's apply this advice.
|
|
667
|
+
|
|
668
|
+
def create
|
|
669
|
+
if title = request['title']
|
|
670
|
+
title.strip!
|
|
671
|
+
if title.empty?
|
|
672
|
+
error("Please enter a title")
|
|
673
|
+
redirect '/new'
|
|
674
|
+
end
|
|
675
|
+
TodoList[title] = {:done => false}
|
|
676
|
+
end
|
|
677
|
+
end
|
|
678
|
+
|
|
679
|
+
First of all we check if we got a request with a value for 'title', if we get
|
|
680
|
+
none we just let the aspect kick in that will redirect the browser to the index.
|
|
681
|
+
Next we strip the title of all spaces around it so we can check if it is empty.
|
|
682
|
+
We will talk about the specifics of our error-handling now.
|
|
683
|
+
|
|
684
|
+
Ramaze has a helper called FlashHelper, that will keep a hash associated with
|
|
685
|
+
the session for one request, afterwards the hash is thrown away. This is
|
|
686
|
+
specifically useful for giving the user feedback while keeping a stateless
|
|
687
|
+
approach.
|
|
688
|
+
|
|
689
|
+
Let me show you our `#error` method (it goes in the private section to
|
|
690
|
+
`#task_status`):
|
|
691
|
+
|
|
692
|
+
def error(message)
|
|
693
|
+
flash[:error] = message
|
|
694
|
+
end
|
|
695
|
+
|
|
696
|
+
Duh, you may say, wouldn't that fit in the one line instead of the call to
|
|
697
|
+
`#error`?
|
|
698
|
+
Indeed, it would, but let me remind you, we have no checks for changing the
|
|
699
|
+
status of a task yet. We will need error-handling there as well, so we just keep
|
|
700
|
+
our code DRY and maintainable by collecting shared behaviour in small pieces.
|
|
701
|
+
|
|
702
|
+
Now on to the `#task_status`:
|
|
703
|
+
|
|
704
|
+
def task_status title, status
|
|
705
|
+
unless task = TodoList[title]
|
|
706
|
+
error "No such Task: `#{title}'"
|
|
707
|
+
redirect_referer
|
|
708
|
+
end
|
|
709
|
+
|
|
710
|
+
task[:done] = status
|
|
711
|
+
TodoList[title] = task
|
|
712
|
+
end
|
|
713
|
+
|
|
714
|
+
That used to look like this:
|
|
715
|
+
|
|
716
|
+
def task_status title, status
|
|
717
|
+
task = TodoList[title]
|
|
718
|
+
task[:done] = status
|
|
719
|
+
TodoList[title] = task
|
|
720
|
+
end
|
|
721
|
+
|
|
722
|
+
So in fact all we added is a check whether a task already exists, set an
|
|
723
|
+
error-message in case it doesn't and redirect to wherever the browser came from.
|
|
724
|
+
|
|
725
|
+
But what about actually showing the error-messages we so carefully set? Well,
|
|
726
|
+
where do we change the view? Right, in the templates. But both templates we have
|
|
727
|
+
so far (index and new) share this behaviour, so let's head over to the Element
|
|
728
|
+
and add in the right place:
|
|
729
|
+
|
|
730
|
+
<body>
|
|
731
|
+
<h1>#{@title}</h1>
|
|
732
|
+
<?r if flash[:error] ?>
|
|
733
|
+
<div class="error">
|
|
734
|
+
\\#{flash[:error]}
|
|
735
|
+
</div>
|
|
736
|
+
<?r end ?>
|
|
737
|
+
#{content}
|
|
738
|
+
</body>
|
|
739
|
+
|
|
740
|
+
The only thing special about it is the `\\#{flash[:error]}`, we have to escape
|
|
741
|
+
the `#` so it won't evaluate this immediately but wait until it is really
|
|
742
|
+
rendered.
|
|
743
|
+
You can add some nifty style if you like.
|
|
744
|
+
|
|
545
745
|
To be continued...
|