ramaze 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (195) hide show
  1. data/Rakefile +4 -12
  2. data/bin/ramaze +95 -171
  3. data/doc/CHANGELOG +387 -4
  4. data/doc/README +81 -13
  5. data/doc/meta/announcement.txt +51 -8
  6. data/doc/meta/configuration.txt +17 -34
  7. data/doc/meta/internals.txt +34 -4
  8. data/doc/migrate/1110_to_1111.txt +131 -0
  9. data/doc/readme_chunks/features.txt +81 -12
  10. data/doc/readme_chunks/installing.txt +0 -1
  11. data/doc/tutorial/todolist.html +293 -65
  12. data/doc/tutorial/{todolist.txt → todolist.mkd} +251 -51
  13. data/examples/blog/main.rb +1 -1
  14. data/examples/blog/src/model.rb +0 -1
  15. data/examples/hello.rb +2 -5
  16. data/examples/templates/template/external.haml +5 -5
  17. data/examples/templates/template/external.liquid +1 -1
  18. data/examples/templates/template/external.mab +8 -8
  19. data/examples/templates/template/external.rem +30 -0
  20. data/examples/templates/template/external.rhtml +6 -7
  21. data/examples/templates/template/external.zmr +13 -9
  22. data/examples/templates/template_amrita2.rb +8 -8
  23. data/examples/templates/template_erubis.rb +11 -11
  24. data/examples/templates/template_ezamar.rb +9 -11
  25. data/examples/templates/template_haml.rb +13 -13
  26. data/examples/templates/template_liquid.rb +10 -10
  27. data/examples/templates/template_markaby.rb +13 -10
  28. data/examples/templates/template_remarkably.rb +59 -0
  29. data/examples/todolist/main.rb +1 -7
  30. data/examples/todolist/src/controller/main.rb +26 -13
  31. data/examples/todolist/src/element/page.rb +5 -0
  32. data/examples/whywiki/main.rb +1 -1
  33. data/lib/proto/main.rb +0 -8
  34. data/lib/proto/public/css/ramaze_error.css +12 -4
  35. data/lib/proto/public/error.zmr +6 -25
  36. data/lib/ramaze.rb +35 -245
  37. data/lib/ramaze/action.rb +21 -0
  38. data/lib/ramaze/adapter.rb +94 -29
  39. data/lib/ramaze/adapter/base.rb +57 -0
  40. data/lib/ramaze/adapter/mongrel.rb +12 -19
  41. data/lib/ramaze/adapter/webrick.rb +21 -20
  42. data/lib/ramaze/cache.rb +47 -3
  43. data/lib/ramaze/cache/memcached.rb +22 -0
  44. data/lib/ramaze/cache/yaml_store.rb +19 -0
  45. data/lib/ramaze/controller.rb +47 -271
  46. data/lib/ramaze/controller/error.rb +43 -0
  47. data/lib/ramaze/controller/render.rb +90 -0
  48. data/lib/ramaze/controller/resolve.rb +147 -0
  49. data/lib/ramaze/dispatcher.rb +41 -9
  50. data/lib/ramaze/dispatcher/file.rb +1 -1
  51. data/lib/ramaze/global.rb +73 -158
  52. data/lib/ramaze/global/dsl.rb +29 -0
  53. data/lib/ramaze/global/globalstruct.rb +90 -0
  54. data/lib/ramaze/helper.rb +1 -1
  55. data/lib/ramaze/helper/aspect.rb +39 -179
  56. data/lib/ramaze/helper/cache.rb +8 -9
  57. data/lib/ramaze/helper/cgi.rb +23 -0
  58. data/lib/ramaze/helper/file.rb +3 -0
  59. data/lib/ramaze/helper/inform.rb +3 -0
  60. data/lib/ramaze/helper/link.rb +56 -63
  61. data/lib/ramaze/helper/nitroform.rb +4 -0
  62. data/lib/ramaze/helper/redirect.rb +1 -1
  63. data/lib/ramaze/inform.rb +6 -2
  64. data/lib/ramaze/inform/analogger.rb +5 -1
  65. data/lib/ramaze/inform/hub.rb +1 -1
  66. data/lib/ramaze/inform/informing.rb +7 -0
  67. data/lib/ramaze/snippets/kernel/aquire.rb +2 -0
  68. data/lib/ramaze/snippets/kernel/constant.rb +2 -0
  69. data/lib/ramaze/snippets/kernel/pretty_inspect.rb +2 -0
  70. data/lib/ramaze/snippets/object/traits.rb +4 -0
  71. data/lib/ramaze/snippets/openstruct/temp.rb +3 -0
  72. data/lib/ramaze/snippets/string/DIVIDE.rb +2 -0
  73. data/lib/ramaze/snippets/string/camel_case.rb +2 -0
  74. data/lib/ramaze/snippets/string/color.rb +2 -0
  75. data/lib/ramaze/snippets/string/each.rb +2 -0
  76. data/lib/ramaze/snippets/string/snake_case.rb +3 -0
  77. data/lib/ramaze/snippets/struct/fill.rb +8 -2
  78. data/lib/ramaze/snippets/struct/values_at.rb +16 -0
  79. data/lib/ramaze/snippets/symbol/to_proc.rb +3 -0
  80. data/lib/ramaze/sourcereload.rb +89 -0
  81. data/lib/ramaze/template.rb +21 -12
  82. data/lib/ramaze/template/amrita2.rb +6 -6
  83. data/lib/ramaze/template/erubis.rb +4 -9
  84. data/lib/ramaze/template/ezamar.rb +13 -57
  85. data/lib/ramaze/template/ezamar/element.rb +10 -12
  86. data/lib/ramaze/template/ezamar/engine.rb +40 -101
  87. data/lib/ramaze/template/ezamar/morpher.rb +3 -3
  88. data/lib/ramaze/template/haml.rb +3 -6
  89. data/lib/ramaze/template/liquid.rb +4 -9
  90. data/lib/ramaze/template/markaby.rb +16 -22
  91. data/lib/ramaze/template/remarkably.rb +28 -0
  92. data/lib/ramaze/tool/mime.rb +2 -0
  93. data/lib/ramaze/tool/record.rb +6 -0
  94. data/lib/ramaze/trinity/request.rb +44 -54
  95. data/lib/ramaze/trinity/response.rb +1 -1
  96. data/lib/ramaze/trinity/session.rb +15 -37
  97. data/lib/ramaze/version.rb +1 -1
  98. data/rake_tasks/gem.rake +2 -2
  99. data/rake_tasks/maintaince.rake +42 -1
  100. data/rake_tasks/spec.rake +45 -0
  101. data/spec/examples/caching.rb +1 -1
  102. data/spec/examples/simple.rb +1 -1
  103. data/spec/examples/templates/template_amrita2.rb +1 -0
  104. data/spec/examples/templates/template_erubis.rb +2 -1
  105. data/spec/examples/templates/template_ezamar.rb +1 -1
  106. data/spec/examples/templates/template_haml.rb +2 -1
  107. data/spec/examples/templates/template_liquid.rb +2 -1
  108. data/spec/examples/templates/template_markaby.rb +2 -1
  109. data/spec/examples/templates/template_remarkably.rb +22 -0
  110. data/spec/examples/todolist.rb +125 -0
  111. data/spec/helper.rb +2 -23
  112. data/spec/helper/minimal.rb +20 -0
  113. data/spec/helper/mock_http.rb +24 -30
  114. data/spec/helper/simple_http.rb +2 -2
  115. data/spec/helper/wrap.rb +6 -9
  116. data/spec/ramaze/adapter.rb +1 -1
  117. data/spec/ramaze/adapter/record.rb +31 -0
  118. data/spec/ramaze/cache.rb +41 -54
  119. data/spec/ramaze/controller.rb +121 -137
  120. data/spec/ramaze/controller/template/list.xhtml +1 -0
  121. data/spec/ramaze/controller/template/other/greet/other.xhtml +1 -0
  122. data/spec/ramaze/controller/template_resolving.rb +27 -3
  123. data/spec/ramaze/element.rb +11 -7
  124. data/spec/ramaze/error.rb +1 -1
  125. data/spec/ramaze/gestalt.rb +2 -0
  126. data/spec/ramaze/helper/aspect.rb +30 -21
  127. data/spec/ramaze/helper/auth.rb +1 -1
  128. data/spec/ramaze/helper/cache.rb +2 -1
  129. data/spec/ramaze/helper/form.rb +14 -11
  130. data/spec/ramaze/helper/link.rb +18 -41
  131. data/spec/ramaze/localize.rb +29 -2
  132. data/spec/ramaze/morpher.rb +23 -12
  133. data/spec/ramaze/params.rb +46 -24
  134. data/spec/ramaze/request.rb +6 -2
  135. data/spec/ramaze/store/yaml.rb +5 -0
  136. data/spec/ramaze/template.rb +22 -27
  137. data/spec/ramaze/template/amrita2.rb +1 -2
  138. data/spec/ramaze/template/erubis.rb +1 -1
  139. data/spec/ramaze/template/ezamar.rb +1 -2
  140. data/spec/ramaze/template/haml.rb +2 -2
  141. data/spec/ramaze/template/haml/with_vars.haml +1 -1
  142. data/spec/ramaze/template/liquid.rb +1 -1
  143. data/spec/ramaze/template/markaby.rb +1 -1
  144. data/spec/ramaze/template/remarkably.rb +56 -0
  145. data/spec/ramaze/template/remarkably/external.rem +8 -0
  146. data/spec/ramaze/template/remarkably/sum.rem +1 -0
  147. metadata +38 -63
  148. data/doc/README.html +0 -637
  149. data/doc/allison/LICENSE +0 -184
  150. data/doc/allison/README +0 -37
  151. data/doc/allison/allison.css +0 -299
  152. data/doc/allison/allison.gif +0 -0
  153. data/doc/allison/allison.js +0 -307
  154. data/doc/allison/allison.rb +0 -287
  155. data/doc/allison/cache/BODY +0 -588
  156. data/doc/allison/cache/CLASS_INDEX +0 -4
  157. data/doc/allison/cache/CLASS_PAGE +0 -1
  158. data/doc/allison/cache/FILE_INDEX +0 -4
  159. data/doc/allison/cache/FILE_PAGE +0 -1
  160. data/doc/allison/cache/FONTS +0 -1
  161. data/doc/allison/cache/FR_INDEX_BODY +0 -1
  162. data/doc/allison/cache/IMGPATH +0 -1
  163. data/doc/allison/cache/INDEX +0 -1
  164. data/doc/allison/cache/JAVASCRIPT +0 -307
  165. data/doc/allison/cache/METHOD_INDEX +0 -4
  166. data/doc/allison/cache/METHOD_LIST +0 -1
  167. data/doc/allison/cache/SRC_PAGE +0 -1
  168. data/doc/allison/cache/STYLE +0 -321
  169. data/doc/allison/cache/URL +0 -1
  170. data/doc/changes.txt +0 -3375
  171. data/doc/changes.xml +0 -3378
  172. data/examples/todolist/conf/benchmark.yaml +0 -35
  173. data/examples/todolist/conf/debug.yaml +0 -34
  174. data/examples/todolist/conf/live.yaml +0 -33
  175. data/examples/todolist/conf/silent.yaml +0 -31
  176. data/examples/todolist/conf/stage.yaml +0 -33
  177. data/examples/todolist/public/css/coderay.css +0 -105
  178. data/examples/todolist/public/css/ramaze_error.css +0 -42
  179. data/lib/proto/conf/benchmark.yaml +0 -21
  180. data/lib/proto/conf/debug.yaml +0 -21
  181. data/lib/proto/conf/live.yaml +0 -21
  182. data/lib/proto/conf/silent.yaml +0 -21
  183. data/lib/proto/conf/stage.yaml +0 -21
  184. data/lib/proto/public/css/coderay.css +0 -105
  185. data/lib/ramaze/http_status.rb +0 -66
  186. data/lib/ramaze/snippets/hash/keys_to_sym.rb +0 -19
  187. data/lib/ramaze/snippets/kernel/method.rb +0 -26
  188. data/lib/ramaze/snippets/method/name.rb +0 -22
  189. data/lib/ramaze/snippets/ramaze/autoreload.rb +0 -135
  190. data/lib/ramaze/snippets/rdoc/usage_no_exit.rb +0 -65
  191. data/spec/all.rb +0 -32
  192. data/spec/ramaze/conf/locale_de.yaml +0 -6
  193. data/spec/ramaze/conf/locale_en.yaml +0 -6
  194. data/spec/ramaze/dependencies.rb +0 -16
  195. 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
- Instead of 'yaml/store' use:
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, parameters|
64
- TodoList[title] = parameters
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, parameters|
87
- status = parameters[:done] ? 'done' : 'not done'
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
- <?r ?> defines an area of ruby-code. Late when the template is transformed into
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 parameters into a block. In that block we can just get the values
101
- of title and status (which we define based on the parameters) displayed 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 fronted of your
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 #index, with a simple and for the moment quite
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 #index is combined with the template
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, parameters|
163
- status = parameters[:done] ? 'done' : 'not done'
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
- <inpyt type="submit" />
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 #create, all we want to do is take the
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 R(self)
249
+ redirect Rs()
251
250
  end
252
251
 
253
252
  That's all folks!
254
253
 
255
- we get the title from the request-object, put it into our TodoList as undone
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, parameters|
282
- if parameters[:done]
280
+ TodoList.original.each do |title, value|
281
+ if value[:done]
283
282
  status = 'done'
284
- toggle = link( R( self, :open, CGI.escape(title) ), :title => 'Open Task' )
283
+ toggle = A('Open Task', :href => Rs(:open, title))
285
284
  else
286
285
  status = 'not done'
287
- toggle = link( R( self, :close, CGI.escape(title) ), :title => 'Close Task' )
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, link and R are both methods that help you do that.
298
- the result will be something like:
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
- R actually is responsible to build the links href, for more information please
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 R(self)
323
+ redirect Rs()
325
324
  end
326
325
 
327
326
  def close title
328
327
  task_status title, true
329
- redirect R(self)
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 #task_status method that takes the title and
343
- status to be set so we don't have to repeat that code in _#open_ and _#close_
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 = link( R( self, :delete, CGI.escape(title) ), :title => '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 R(self)
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 _#render_. Then it will go and hand the content in
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 _#content_ method that we call with _#{content}_ inside the string in
443
- _#render_.
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 to get it line up properly and look actually structured.
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 Page element and add some style sheet like that:
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
- And yes, if you don't like tables (though this is an entirely legit use in my opinion, you can just do it like you want, using nested lists or divs/spans, replacing the open/close and delete links with nice images and changing the style according to the status.
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...