Pistos-ramaze 2008.09

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.
Files changed (588) hide show
  1. data/README.markdown +481 -0
  2. data/Rakefile +228 -0
  3. data/benchmark/results.txt +131 -0
  4. data/benchmark/run.rb +362 -0
  5. data/benchmark/suite/minimal.rb +13 -0
  6. data/benchmark/suite/no_informer.rb +9 -0
  7. data/benchmark/suite/no_sessions.rb +10 -0
  8. data/benchmark/suite/no_template.rb +9 -0
  9. data/benchmark/suite/simple.rb +7 -0
  10. data/benchmark/suite/template_amrita2.rb +17 -0
  11. data/benchmark/suite/template_builder.rb +12 -0
  12. data/benchmark/suite/template_erubis.rb +10 -0
  13. data/benchmark/suite/template_ezamar.rb +10 -0
  14. data/benchmark/suite/template_haml.rb +15 -0
  15. data/benchmark/suite/template_liquid.rb +13 -0
  16. data/benchmark/suite/template_markaby.rb +11 -0
  17. data/benchmark/suite/template_nagoro.rb +10 -0
  18. data/benchmark/suite/template_redcloth.rb +15 -0
  19. data/benchmark/suite/template_tenjin.rb +10 -0
  20. data/benchmark/test.rb +35 -0
  21. data/bin/ramaze +80 -0
  22. data/doc/AUTHORS +29 -0
  23. data/doc/CHANGELOG +19530 -0
  24. data/doc/COPYING +56 -0
  25. data/doc/FAQ +92 -0
  26. data/doc/GPL +339 -0
  27. data/doc/INSTALL +92 -0
  28. data/doc/LEGAL +26 -0
  29. data/doc/TODO +29 -0
  30. data/doc/meta/announcement.txt +99 -0
  31. data/doc/meta/configuration.txt +163 -0
  32. data/doc/meta/internals.txt +278 -0
  33. data/doc/meta/users.kml +64 -0
  34. data/doc/readme_chunks/appendix.txt +10 -0
  35. data/doc/readme_chunks/examples.txt +38 -0
  36. data/doc/readme_chunks/features.txt +148 -0
  37. data/doc/readme_chunks/getting_help.txt +5 -0
  38. data/doc/readme_chunks/getting_started.txt +18 -0
  39. data/doc/readme_chunks/installing.txt +92 -0
  40. data/doc/readme_chunks/introduction.txt +18 -0
  41. data/doc/readme_chunks/principles.txt +56 -0
  42. data/doc/readme_chunks/thanks.txt +59 -0
  43. data/doc/tutorial/todolist.html +742 -0
  44. data/doc/tutorial/todolist.mkd +787 -0
  45. data/examples/app/auth/auth.rb +54 -0
  46. data/examples/app/auth/template/layout.haml +20 -0
  47. data/examples/app/auth/template/login.haml +16 -0
  48. data/examples/app/blog/README +3 -0
  49. data/examples/app/blog/controller/main.rb +29 -0
  50. data/examples/app/blog/model/entry.rb +30 -0
  51. data/examples/app/blog/public/styles/blog.css +132 -0
  52. data/examples/app/blog/spec/blog.rb +87 -0
  53. data/examples/app/blog/start.rb +7 -0
  54. data/examples/app/blog/view/edit.xhtml +17 -0
  55. data/examples/app/blog/view/index.xhtml +17 -0
  56. data/examples/app/blog/view/layout.xhtml +11 -0
  57. data/examples/app/blog/view/new.xhtml +16 -0
  58. data/examples/app/chat/model/history.rb +36 -0
  59. data/examples/app/chat/model/message.rb +7 -0
  60. data/examples/app/chat/public/css/chat.css +13 -0
  61. data/examples/app/chat/public/js/chat.js +22 -0
  62. data/examples/app/chat/public/js/jquery.js +3436 -0
  63. data/examples/app/chat/start.rb +40 -0
  64. data/examples/app/chat/view/chat.xhtml +9 -0
  65. data/examples/app/chat/view/index.xhtml +7 -0
  66. data/examples/app/chat/view/layout.xhtml +13 -0
  67. data/examples/app/localization/start.rb +35 -0
  68. data/examples/app/rapaste/Rakefile +34 -0
  69. data/examples/app/rapaste/controller/paste.rb +101 -0
  70. data/examples/app/rapaste/model/paste.rb +58 -0
  71. data/examples/app/rapaste/public/css/active4d.css +114 -0
  72. data/examples/app/rapaste/public/css/all_hallows_eve.css +72 -0
  73. data/examples/app/rapaste/public/css/amy.css +147 -0
  74. data/examples/app/rapaste/public/css/blackboard.css +88 -0
  75. data/examples/app/rapaste/public/css/brilliance_black.css +605 -0
  76. data/examples/app/rapaste/public/css/brilliance_dull.css +599 -0
  77. data/examples/app/rapaste/public/css/cobalt.css +149 -0
  78. data/examples/app/rapaste/public/css/dawn.css +121 -0
  79. data/examples/app/rapaste/public/css/display.css +197 -0
  80. data/examples/app/rapaste/public/css/eiffel.css +121 -0
  81. data/examples/app/rapaste/public/css/espresso_libre.css +109 -0
  82. data/examples/app/rapaste/public/css/idle.css +62 -0
  83. data/examples/app/rapaste/public/css/iplastic.css +80 -0
  84. data/examples/app/rapaste/public/css/lazy.css +73 -0
  85. data/examples/app/rapaste/public/css/mac_classic.css +123 -0
  86. data/examples/app/rapaste/public/css/magicwb_amiga.css +104 -0
  87. data/examples/app/rapaste/public/css/pastels_on_dark.css +188 -0
  88. data/examples/app/rapaste/public/css/slush_poppies.css +85 -0
  89. data/examples/app/rapaste/public/css/spacecadet.css +51 -0
  90. data/examples/app/rapaste/public/css/sunburst.css +180 -0
  91. data/examples/app/rapaste/public/css/twilight.css +137 -0
  92. data/examples/app/rapaste/public/css/zenburnesque.css +91 -0
  93. data/examples/app/rapaste/public/js/jquery.js +11 -0
  94. data/examples/app/rapaste/spec/rapaste.rb +51 -0
  95. data/examples/app/rapaste/start.rb +25 -0
  96. data/examples/app/rapaste/view/copy.xhtml +10 -0
  97. data/examples/app/rapaste/view/index.xhtml +9 -0
  98. data/examples/app/rapaste/view/layout.xhtml +25 -0
  99. data/examples/app/rapaste/view/list.xhtml +29 -0
  100. data/examples/app/rapaste/view/search.xhtml +41 -0
  101. data/examples/app/rapaste/view/view.xhtml +37 -0
  102. data/examples/app/sourceview/public/coderay.css +104 -0
  103. data/examples/app/sourceview/public/images/file.gif +0 -0
  104. data/examples/app/sourceview/public/images/folder.gif +0 -0
  105. data/examples/app/sourceview/public/images/tv-collapsable-last.gif +0 -0
  106. data/examples/app/sourceview/public/images/tv-collapsable.gif +0 -0
  107. data/examples/app/sourceview/public/images/tv-expandable-last.gif +0 -0
  108. data/examples/app/sourceview/public/images/tv-expandable.gif +0 -0
  109. data/examples/app/sourceview/public/images/tv-item-last.gif +0 -0
  110. data/examples/app/sourceview/public/images/tv-item.gif +0 -0
  111. data/examples/app/sourceview/public/jquery.js +11 -0
  112. data/examples/app/sourceview/public/jquery.treeview.css +48 -0
  113. data/examples/app/sourceview/public/jquery.treeview.js +223 -0
  114. data/examples/app/sourceview/public/sourceview.js +52 -0
  115. data/examples/app/sourceview/sourceview.rb +77 -0
  116. data/examples/app/sourceview/template/index.haml +59 -0
  117. data/examples/app/todolist/README +1 -0
  118. data/examples/app/todolist/public/favicon.ico +0 -0
  119. data/examples/app/todolist/public/js/jquery.js +1923 -0
  120. data/examples/app/todolist/public/ramaze.png +0 -0
  121. data/examples/app/todolist/spec/todolist.rb +132 -0
  122. data/examples/app/todolist/src/controller/main.rb +70 -0
  123. data/examples/app/todolist/src/element/page.rb +31 -0
  124. data/examples/app/todolist/src/model.rb +14 -0
  125. data/examples/app/todolist/start.rb +11 -0
  126. data/examples/app/todolist/template/index.xhtml +17 -0
  127. data/examples/app/todolist/template/new.xhtml +7 -0
  128. data/examples/app/upload/start.rb +19 -0
  129. data/examples/app/upload/view/index.xhtml +25 -0
  130. data/examples/app/whywiki/spec/whywiki.rb +58 -0
  131. data/examples/app/whywiki/start.rb +46 -0
  132. data/examples/app/whywiki/template/edit.xhtml +14 -0
  133. data/examples/app/whywiki/template/show.xhtml +18 -0
  134. data/examples/app/wikore/spec/wikore.rb +111 -0
  135. data/examples/app/wikore/src/controller.rb +80 -0
  136. data/examples/app/wikore/src/model.rb +53 -0
  137. data/examples/app/wikore/start.rb +9 -0
  138. data/examples/app/wikore/template/index.xhtml +8 -0
  139. data/examples/app/wiktacular/README +2 -0
  140. data/examples/app/wiktacular/mkd/link/2007-07-20_19-45-51.mkd +1 -0
  141. data/examples/app/wiktacular/mkd/link/current.mkd +1 -0
  142. data/examples/app/wiktacular/mkd/main/2007-07-20_16-31-33.mkd +1 -0
  143. data/examples/app/wiktacular/mkd/main/2007-07-20_19-21-12.mkd +1 -0
  144. data/examples/app/wiktacular/mkd/main/2007-07-20_19-23-10.mkd +2 -0
  145. data/examples/app/wiktacular/mkd/main/2007-07-20_19-45-07.mkd +2 -0
  146. data/examples/app/wiktacular/mkd/main/current.mkd +2 -0
  147. data/examples/app/wiktacular/mkd/markdown/current.mkd +3 -0
  148. data/examples/app/wiktacular/mkd/testing/2007-07-20_16-43-46.mkd +2 -0
  149. data/examples/app/wiktacular/mkd/testing/2007-07-20_19-43-50.mkd +3 -0
  150. data/examples/app/wiktacular/mkd/testing/2007-07-21_18-46-01.mkd +11 -0
  151. data/examples/app/wiktacular/mkd/testing/2007-07-21_18-46-32.mkd +13 -0
  152. data/examples/app/wiktacular/mkd/testing/2007-07-21_18-47-08.mkd +17 -0
  153. data/examples/app/wiktacular/mkd/testing/2007-07-21_18-47-54.mkd +17 -0
  154. data/examples/app/wiktacular/mkd/testing/current.mkd +17 -0
  155. data/examples/app/wiktacular/public/favicon.ico +0 -0
  156. data/examples/app/wiktacular/public/screen.css +72 -0
  157. data/examples/app/wiktacular/spec/wiktacular.rb +157 -0
  158. data/examples/app/wiktacular/src/controller.rb +55 -0
  159. data/examples/app/wiktacular/src/model.rb +102 -0
  160. data/examples/app/wiktacular/start.rb +8 -0
  161. data/examples/app/wiktacular/template/edit.xhtml +6 -0
  162. data/examples/app/wiktacular/template/html_layout.xhtml +27 -0
  163. data/examples/app/wiktacular/template/index.xhtml +9 -0
  164. data/examples/app/wiktacular/template/new.xhtml +6 -0
  165. data/examples/basic/element.rb +45 -0
  166. data/examples/basic/gestalt.rb +27 -0
  167. data/examples/basic/hello.rb +15 -0
  168. data/examples/basic/layout.rb +28 -0
  169. data/examples/basic/linking.rb +29 -0
  170. data/examples/basic/simple.rb +56 -0
  171. data/examples/helpers/cache.rb +31 -0
  172. data/examples/helpers/form_with_sequel.rb +24 -0
  173. data/examples/helpers/httpdigest.rb +50 -0
  174. data/examples/helpers/identity.rb +18 -0
  175. data/examples/helpers/nitro_form.rb +23 -0
  176. data/examples/helpers/paginate.rb +71 -0
  177. data/examples/helpers/provide.rb +23 -0
  178. data/examples/helpers/rest.rb +28 -0
  179. data/examples/helpers/simple_captcha.rb +29 -0
  180. data/examples/misc/css.rb +37 -0
  181. data/examples/misc/facebook.rb +159 -0
  182. data/examples/misc/memleak_detector.rb +32 -0
  183. data/examples/misc/nagoro_element.rb +43 -0
  184. data/examples/misc/ramaise.rb +132 -0
  185. data/examples/misc/rapp.rb +45 -0
  186. data/examples/misc/sequel_scaffolding.rb +34 -0
  187. data/examples/misc/simple_auth.rb +35 -0
  188. data/examples/templates/template/external.amrita +19 -0
  189. data/examples/templates/template/external.haml +22 -0
  190. data/examples/templates/template/external.liquid +28 -0
  191. data/examples/templates/template/external.mab +30 -0
  192. data/examples/templates/template/external.nag +28 -0
  193. data/examples/templates/template/external.redcloth +19 -0
  194. data/examples/templates/template/external.rem +30 -0
  195. data/examples/templates/template/external.rhtml +28 -0
  196. data/examples/templates/template/external.tenjin +28 -0
  197. data/examples/templates/template/external.xsl +57 -0
  198. data/examples/templates/template/external.zmr +28 -0
  199. data/examples/templates/template_amrita2.rb +74 -0
  200. data/examples/templates/template_erubis.rb +53 -0
  201. data/examples/templates/template_ezamar.rb +50 -0
  202. data/examples/templates/template_haml.rb +50 -0
  203. data/examples/templates/template_liquid.rb +65 -0
  204. data/examples/templates/template_markaby.rb +58 -0
  205. data/examples/templates/template_nagoro.rb +51 -0
  206. data/examples/templates/template_redcloth.rb +59 -0
  207. data/examples/templates/template_remarkably.rb +55 -0
  208. data/examples/templates/template_tenjin.rb +53 -0
  209. data/examples/templates/template_xslt.rb +49 -0
  210. data/lib/proto/controller/init.rb +10 -0
  211. data/lib/proto/controller/main.rb +20 -0
  212. data/lib/proto/model/init.rb +4 -0
  213. data/lib/proto/public/css/ramaze_error.css +90 -0
  214. data/lib/proto/public/dispatch.fcgi +11 -0
  215. data/lib/proto/public/favicon.ico +0 -0
  216. data/lib/proto/public/js/jquery.js +3549 -0
  217. data/lib/proto/public/ramaze.png +0 -0
  218. data/lib/proto/spec/main.rb +25 -0
  219. data/lib/proto/start.rb +8 -0
  220. data/lib/proto/start.ru +16 -0
  221. data/lib/proto/view/error.xhtml +64 -0
  222. data/lib/proto/view/index.xhtml +34 -0
  223. data/lib/proto/view/page.xhtml +27 -0
  224. data/lib/ramaze/action/render.rb +191 -0
  225. data/lib/ramaze/action.rb +153 -0
  226. data/lib/ramaze/adapter/base.rb +128 -0
  227. data/lib/ramaze/adapter/cgi.rb +20 -0
  228. data/lib/ramaze/adapter/ebb.rb +18 -0
  229. data/lib/ramaze/adapter/evented_mongrel.rb +7 -0
  230. data/lib/ramaze/adapter/fake.rb +12 -0
  231. data/lib/ramaze/adapter/fcgi.rb +18 -0
  232. data/lib/ramaze/adapter/lsws.rb +19 -0
  233. data/lib/ramaze/adapter/mongrel.rb +21 -0
  234. data/lib/ramaze/adapter/scgi.rb +18 -0
  235. data/lib/ramaze/adapter/swiftiplied_mongrel.rb +7 -0
  236. data/lib/ramaze/adapter/thin.rb +17 -0
  237. data/lib/ramaze/adapter/webrick.rb +43 -0
  238. data/lib/ramaze/adapter.rb +97 -0
  239. data/lib/ramaze/cache/memcached.rb +69 -0
  240. data/lib/ramaze/cache/memory.rb +6 -0
  241. data/lib/ramaze/cache/yaml_store.rb +68 -0
  242. data/lib/ramaze/cache.rb +113 -0
  243. data/lib/ramaze/contrib/auto_params/get_args.rb +58 -0
  244. data/lib/ramaze/contrib/auto_params.rb +135 -0
  245. data/lib/ramaze/contrib/email.rb +84 -0
  246. data/lib/ramaze/contrib/facebook/facebook.rb +171 -0
  247. data/lib/ramaze/contrib/facebook.rb +23 -0
  248. data/lib/ramaze/contrib/file_cache.rb +65 -0
  249. data/lib/ramaze/contrib/gems.rb +78 -0
  250. data/lib/ramaze/contrib/gettext/mo.rb +155 -0
  251. data/lib/ramaze/contrib/gettext/parser.rb +46 -0
  252. data/lib/ramaze/contrib/gettext/po.rb +109 -0
  253. data/lib/ramaze/contrib/gettext.rb +113 -0
  254. data/lib/ramaze/contrib/gzip_filter.rb +69 -0
  255. data/lib/ramaze/contrib/maruku_uv.rb +59 -0
  256. data/lib/ramaze/contrib/profiling.rb +36 -0
  257. data/lib/ramaze/contrib/rest.rb +17 -0
  258. data/lib/ramaze/contrib/sequel/create_join.rb +25 -0
  259. data/lib/ramaze/contrib/sequel/fill.rb +12 -0
  260. data/lib/ramaze/contrib/sequel/form_field.rb +129 -0
  261. data/lib/ramaze/contrib/sequel/image.rb +198 -0
  262. data/lib/ramaze/contrib/sequel/relation.rb +82 -0
  263. data/lib/ramaze/contrib/sequel_cache.rb +92 -0
  264. data/lib/ramaze/contrib.rb +82 -0
  265. data/lib/ramaze/controller/error.rb +46 -0
  266. data/lib/ramaze/controller/main.rb +2 -0
  267. data/lib/ramaze/controller/resolve.rb +273 -0
  268. data/lib/ramaze/controller.rb +280 -0
  269. data/lib/ramaze/current/request.rb +205 -0
  270. data/lib/ramaze/current/response.rb +39 -0
  271. data/lib/ramaze/current/session/flash.rb +87 -0
  272. data/lib/ramaze/current/session/hash.rb +66 -0
  273. data/lib/ramaze/current/session.rb +181 -0
  274. data/lib/ramaze/current.rb +110 -0
  275. data/lib/ramaze/dispatcher/action.rb +48 -0
  276. data/lib/ramaze/dispatcher/directory.rb +119 -0
  277. data/lib/ramaze/dispatcher/error.rb +108 -0
  278. data/lib/ramaze/dispatcher/file.rb +95 -0
  279. data/lib/ramaze/dispatcher.rb +145 -0
  280. data/lib/ramaze/error.rb +24 -0
  281. data/lib/ramaze/gestalt.rb +124 -0
  282. data/lib/ramaze/helper/aspect.rb +106 -0
  283. data/lib/ramaze/helper/auth.rb +125 -0
  284. data/lib/ramaze/helper/cache.rb +140 -0
  285. data/lib/ramaze/helper/cgi.rb +39 -0
  286. data/lib/ramaze/helper/flash.rb +59 -0
  287. data/lib/ramaze/helper/form.rb +281 -0
  288. data/lib/ramaze/helper/formatting.rb +158 -0
  289. data/lib/ramaze/helper/gestalt.rb +15 -0
  290. data/lib/ramaze/helper/gravatar.rb +15 -0
  291. data/lib/ramaze/helper/httpdigest.rb +59 -0
  292. data/lib/ramaze/helper/identity.rb +119 -0
  293. data/lib/ramaze/helper/link.rb +122 -0
  294. data/lib/ramaze/helper/markaby.rb +31 -0
  295. data/lib/ramaze/helper/maruku.rb +7 -0
  296. data/lib/ramaze/helper/nitroform.rb +14 -0
  297. data/lib/ramaze/helper/pager.rb +366 -0
  298. data/lib/ramaze/helper/paginate.rb +234 -0
  299. data/lib/ramaze/helper/partial.rb +105 -0
  300. data/lib/ramaze/helper/redirect.rb +82 -0
  301. data/lib/ramaze/helper/rest.rb +43 -0
  302. data/lib/ramaze/helper/sendfile.rb +16 -0
  303. data/lib/ramaze/helper/sequel.rb +55 -0
  304. data/lib/ramaze/helper/simple_captcha.rb +31 -0
  305. data/lib/ramaze/helper/stack.rb +77 -0
  306. data/lib/ramaze/helper/tagz.rb +19 -0
  307. data/lib/ramaze/helper/thread.rb +17 -0
  308. data/lib/ramaze/helper/ultraviolet.rb +44 -0
  309. data/lib/ramaze/helper/user.rb +110 -0
  310. data/lib/ramaze/helper/xhtml.rb +23 -0
  311. data/lib/ramaze/helper.rb +79 -0
  312. data/lib/ramaze/log/analogger.rb +40 -0
  313. data/lib/ramaze/log/growl.rb +38 -0
  314. data/lib/ramaze/log/hub.rb +41 -0
  315. data/lib/ramaze/log/informer.rb +128 -0
  316. data/lib/ramaze/log/knotify.rb +28 -0
  317. data/lib/ramaze/log/logger.rb +26 -0
  318. data/lib/ramaze/log/logging.rb +89 -0
  319. data/lib/ramaze/log/syslog.rb +51 -0
  320. data/lib/ramaze/log/xosd.rb +92 -0
  321. data/lib/ramaze/log.rb +27 -0
  322. data/lib/ramaze/option/dsl.rb +45 -0
  323. data/lib/ramaze/option/holder.rb +131 -0
  324. data/lib/ramaze/option/merger.rb +108 -0
  325. data/lib/ramaze/option.rb +156 -0
  326. data/lib/ramaze/reloader.rb +186 -0
  327. data/lib/ramaze/route.rb +97 -0
  328. data/lib/ramaze/setup.rb +50 -0
  329. data/lib/ramaze/snippets/array/put_within.rb +44 -0
  330. data/lib/ramaze/snippets/binding/locals.rb +25 -0
  331. data/lib/ramaze/snippets/blankslate.rb +7 -0
  332. data/lib/ramaze/snippets/dictionary.rb +504 -0
  333. data/lib/ramaze/snippets/divide.rb +20 -0
  334. data/lib/ramaze/snippets/fiber.rb +63 -0
  335. data/lib/ramaze/snippets/kernel/constant.rb +41 -0
  336. data/lib/ramaze/snippets/kernel/pretty_inspect.rb +21 -0
  337. data/lib/ramaze/snippets/metaid.rb +17 -0
  338. data/lib/ramaze/snippets/numeric/filesize_format.rb +32 -0
  339. data/lib/ramaze/snippets/numeric/time.rb +63 -0
  340. data/lib/ramaze/snippets/object/__dir__.rb +29 -0
  341. data/lib/ramaze/snippets/object/acquire.rb +40 -0
  342. data/lib/ramaze/snippets/object/instance_variable_defined.rb +19 -0
  343. data/lib/ramaze/snippets/object/pretty.rb +16 -0
  344. data/lib/ramaze/snippets/object/scope.rb +18 -0
  345. data/lib/ramaze/snippets/object/traits.rb +76 -0
  346. data/lib/ramaze/snippets/ordered_set.rb +51 -0
  347. data/lib/ramaze/snippets/proc/locals.rb +19 -0
  348. data/lib/ramaze/snippets/ramaze/caller_info.rb +30 -0
  349. data/lib/ramaze/snippets/ramaze/caller_lines.rb +51 -0
  350. data/lib/ramaze/snippets/ramaze/deprecated.rb +20 -0
  351. data/lib/ramaze/snippets/ramaze/fiber.rb +24 -0
  352. data/lib/ramaze/snippets/ramaze/state.rb +86 -0
  353. data/lib/ramaze/snippets/ramaze/struct.rb +45 -0
  354. data/lib/ramaze/snippets/string/camel_case.rb +21 -0
  355. data/lib/ramaze/snippets/string/color.rb +31 -0
  356. data/lib/ramaze/snippets/string/each.rb +19 -0
  357. data/lib/ramaze/snippets/string/end_with.rb +20 -0
  358. data/lib/ramaze/snippets/string/esc.rb +34 -0
  359. data/lib/ramaze/snippets/string/ord.rb +21 -0
  360. data/lib/ramaze/snippets/string/snake_case.rb +21 -0
  361. data/lib/ramaze/snippets/string/start_with.rb +19 -0
  362. data/lib/ramaze/snippets/string/unindent.rb +28 -0
  363. data/lib/ramaze/snippets/thread/into.rb +18 -0
  364. data/lib/ramaze/snippets.rb +22 -0
  365. data/lib/ramaze/spec/helper/bacon.rb +7 -0
  366. data/lib/ramaze/spec/helper/browser.rb +88 -0
  367. data/lib/ramaze/spec/helper/mock_http.rb +63 -0
  368. data/lib/ramaze/spec/helper/pretty_output.rb +82 -0
  369. data/lib/ramaze/spec/helper/requester.rb +63 -0
  370. data/lib/ramaze/spec/helper/simple_http.rb +434 -0
  371. data/lib/ramaze/spec/helper/snippets.rb +14 -0
  372. data/lib/ramaze/spec/helper.rb +135 -0
  373. data/lib/ramaze/spec.rb +1 -0
  374. data/lib/ramaze/store/default.rb +109 -0
  375. data/lib/ramaze/template/amrita2.rb +45 -0
  376. data/lib/ramaze/template/builder.rb +28 -0
  377. data/lib/ramaze/template/erubis.rb +41 -0
  378. data/lib/ramaze/template/ezamar/element.rb +169 -0
  379. data/lib/ramaze/template/ezamar/engine.rb +76 -0
  380. data/lib/ramaze/template/ezamar/morpher.rb +135 -0
  381. data/lib/ramaze/template/ezamar/render_partial.rb +31 -0
  382. data/lib/ramaze/template/ezamar/textpow.syntax +34 -0
  383. data/lib/ramaze/template/ezamar.rb +42 -0
  384. data/lib/ramaze/template/haml.rb +37 -0
  385. data/lib/ramaze/template/liquid.rb +36 -0
  386. data/lib/ramaze/template/markaby.rb +52 -0
  387. data/lib/ramaze/template/maruku.rb +34 -0
  388. data/lib/ramaze/template/nagoro.rb +52 -0
  389. data/lib/ramaze/template/none.rb +14 -0
  390. data/lib/ramaze/template/redcloth.rb +25 -0
  391. data/lib/ramaze/template/remarkably.rb +38 -0
  392. data/lib/ramaze/template/sass.rb +37 -0
  393. data/lib/ramaze/template/tagz.rb +79 -0
  394. data/lib/ramaze/template/tenjin.rb +74 -0
  395. data/lib/ramaze/template/xslt.rb +100 -0
  396. data/lib/ramaze/template.rb +87 -0
  397. data/lib/ramaze/tool/create.rb +48 -0
  398. data/lib/ramaze/tool/daemonize.rb +37 -0
  399. data/lib/ramaze/tool/localize.rb +202 -0
  400. data/lib/ramaze/tool/mime.rb +35 -0
  401. data/lib/ramaze/tool/mime_types.yaml +615 -0
  402. data/lib/ramaze/tool/project_creator.rb +110 -0
  403. data/lib/ramaze/tool/record.rb +6 -0
  404. data/lib/ramaze/tool.rb +9 -0
  405. data/lib/ramaze/trinity.rb +16 -0
  406. data/lib/ramaze/version.rb +6 -0
  407. data/lib/ramaze.rb +133 -0
  408. data/lib/vendor/bacon.rb +323 -0
  409. data/rake_tasks/conf.rake +71 -0
  410. data/rake_tasks/coverage.rake +46 -0
  411. data/rake_tasks/gem.rake +74 -0
  412. data/rake_tasks/git.rake +41 -0
  413. data/rake_tasks/maintenance.rake +386 -0
  414. data/rake_tasks/metric.rake +24 -0
  415. data/rake_tasks/release.rake +76 -0
  416. data/rake_tasks/spec.rake +61 -0
  417. data/ramaze.gemspec +773 -0
  418. data/spec/contrib/auto_params.rb +121 -0
  419. data/spec/contrib/profiling.rb +29 -0
  420. data/spec/contrib/sequel/fill.rb +47 -0
  421. data/spec/examples/caching.rb +19 -0
  422. data/spec/examples/css.rb +15 -0
  423. data/spec/examples/element.rb +15 -0
  424. data/spec/examples/hello.rb +11 -0
  425. data/spec/examples/linking.rb +18 -0
  426. data/spec/examples/simple.rb +45 -0
  427. data/spec/examples/simple_auth.rb +32 -0
  428. data/spec/examples/templates/template_amrita2.rb +16 -0
  429. data/spec/examples/templates/template_erubis.rb +23 -0
  430. data/spec/examples/templates/template_ezamar.rb +23 -0
  431. data/spec/examples/templates/template_haml.rb +23 -0
  432. data/spec/examples/templates/template_liquid.rb +29 -0
  433. data/spec/examples/templates/template_markaby.rb +23 -0
  434. data/spec/examples/templates/template_redcloth.rb +28 -0
  435. data/spec/examples/templates/template_remarkably.rb +23 -0
  436. data/spec/examples/templates/template_tenjin.rb +28 -0
  437. data/spec/helper.rb +3 -0
  438. data/spec/ramaze/action/basics.rb +36 -0
  439. data/spec/ramaze/action/cache.rb +87 -0
  440. data/spec/ramaze/action/file_cache.rb +70 -0
  441. data/spec/ramaze/action/layout.rb +190 -0
  442. data/spec/ramaze/action/render.rb +31 -0
  443. data/spec/ramaze/action/view/bar.xhtml +1 -0
  444. data/spec/ramaze/action/view/instancevars/layout.xhtml +1 -0
  445. data/spec/ramaze/action/view/other_wrapper.xhtml +1 -0
  446. data/spec/ramaze/action/view/single_wrapper.xhtml +1 -0
  447. data/spec/ramaze/action/view/sub/sub_wrapper.xhtml +1 -0
  448. data/spec/ramaze/adapter/ebb.rb +12 -0
  449. data/spec/ramaze/adapter/mongrel.rb +12 -0
  450. data/spec/ramaze/adapter/record.rb +31 -0
  451. data/spec/ramaze/adapter/webrick.rb +12 -0
  452. data/spec/ramaze/adapter.rb +49 -0
  453. data/spec/ramaze/cache.rb +140 -0
  454. data/spec/ramaze/controller/actionless_templates.rb +32 -0
  455. data/spec/ramaze/controller/resolve.rb +32 -0
  456. data/spec/ramaze/controller/subclass.rb +36 -0
  457. data/spec/ramaze/controller/template_resolving.rb +113 -0
  458. data/spec/ramaze/controller/view/bar.xhtml +1 -0
  459. data/spec/ramaze/controller/view/base/another.xhtml +1 -0
  460. data/spec/ramaze/controller/view/greet.xhtml +1 -0
  461. data/spec/ramaze/controller/view/list.xhtml +1 -0
  462. data/spec/ramaze/controller/view/other/greet/other.xhtml +1 -0
  463. data/spec/ramaze/controller/view/other_wrapper.xhtml +1 -0
  464. data/spec/ramaze/controller.rb +180 -0
  465. data/spec/ramaze/current/request.rb +30 -0
  466. data/spec/ramaze/current/session.rb +97 -0
  467. data/spec/ramaze/dispatcher/directory.rb +55 -0
  468. data/spec/ramaze/dispatcher/file.rb +60 -0
  469. data/spec/ramaze/dispatcher/public/favicon.ico +0 -0
  470. data/spec/ramaze/dispatcher/public/file name.txt +1 -0
  471. data/spec/ramaze/dispatcher/public/test_download.css +141 -0
  472. data/spec/ramaze/dispatcher.rb +31 -0
  473. data/spec/ramaze/element.rb +107 -0
  474. data/spec/ramaze/error.rb +94 -0
  475. data/spec/ramaze/gestalt.rb +131 -0
  476. data/spec/ramaze/helper/aspect.rb +101 -0
  477. data/spec/ramaze/helper/auth.rb +66 -0
  478. data/spec/ramaze/helper/cache.rb +160 -0
  479. data/spec/ramaze/helper/cgi.rb +43 -0
  480. data/spec/ramaze/helper/file.rb +18 -0
  481. data/spec/ramaze/helper/flash.rb +133 -0
  482. data/spec/ramaze/helper/form.rb +118 -0
  483. data/spec/ramaze/helper/formatting.rb +54 -0
  484. data/spec/ramaze/helper/link.rb +124 -0
  485. data/spec/ramaze/helper/pager.rb +99 -0
  486. data/spec/ramaze/helper/partial.rb +88 -0
  487. data/spec/ramaze/helper/redirect.rb +112 -0
  488. data/spec/ramaze/helper/simple_captcha.rb +22 -0
  489. data/spec/ramaze/helper/stack.rb +73 -0
  490. data/spec/ramaze/helper/user.rb +43 -0
  491. data/spec/ramaze/helper/view/locals.xhtml +1 -0
  492. data/spec/ramaze/helper/view/loop.xhtml +4 -0
  493. data/spec/ramaze/helper/view/num.xhtml +1 -0
  494. data/spec/ramaze/helper/view/partial.xhtml +1 -0
  495. data/spec/ramaze/helper/view/recursive.xhtml +8 -0
  496. data/spec/ramaze/helper/view/recursive_local_ivars.xhtml +7 -0
  497. data/spec/ramaze/helper/view/recursive_locals.xhtml +7 -0
  498. data/spec/ramaze/helper/view/test_template.xhtml +1 -0
  499. data/spec/ramaze/localize.rb +89 -0
  500. data/spec/ramaze/log/informer.rb +72 -0
  501. data/spec/ramaze/log/syslog.rb +73 -0
  502. data/spec/ramaze/morpher.rb +111 -0
  503. data/spec/ramaze/params.rb +157 -0
  504. data/spec/ramaze/public/error404.xhtml +1 -0
  505. data/spec/ramaze/public/favicon.ico +0 -0
  506. data/spec/ramaze/public/ramaze.png +0 -0
  507. data/spec/ramaze/public/test_download.css +141 -0
  508. data/spec/ramaze/request/ebb.rb +9 -0
  509. data/spec/ramaze/request/mongrel.rb +9 -0
  510. data/spec/ramaze/request/thin.rb +9 -0
  511. data/spec/ramaze/request/webrick.rb +5 -0
  512. data/spec/ramaze/request.rb +185 -0
  513. data/spec/ramaze/rewrite/file.css +1 -0
  514. data/spec/ramaze/rewrite.rb +36 -0
  515. data/spec/ramaze/route.rb +131 -0
  516. data/spec/ramaze/session.rb +94 -0
  517. data/spec/ramaze/store/default.rb +71 -0
  518. data/spec/ramaze/struct.rb +47 -0
  519. data/spec/ramaze/template/amrita2/external.amrita +6 -0
  520. data/spec/ramaze/template/amrita2/sum.amrita +1 -0
  521. data/spec/ramaze/template/amrita2.rb +50 -0
  522. data/spec/ramaze/template/builder/external.rxml +3 -0
  523. data/spec/ramaze/template/builder.rb +51 -0
  524. data/spec/ramaze/template/erubis/sum.rhtml +1 -0
  525. data/spec/ramaze/template/erubis.rb +41 -0
  526. data/spec/ramaze/template/ezamar/another/long/action.zmr +1 -0
  527. data/spec/ramaze/template/ezamar/combined.zmr +1 -0
  528. data/spec/ramaze/template/ezamar/file_only.zmr +1 -0
  529. data/spec/ramaze/template/ezamar/index.zmr +1 -0
  530. data/spec/ramaze/template/ezamar/nested.zmr +1 -0
  531. data/spec/ramaze/template/ezamar/other__index.xhtml +1 -0
  532. data/spec/ramaze/template/ezamar/some__long__action.zmr +1 -0
  533. data/spec/ramaze/template/ezamar/sum.zmr +1 -0
  534. data/spec/ramaze/template/ezamar.rb +63 -0
  535. data/spec/ramaze/template/haml/index.haml +5 -0
  536. data/spec/ramaze/template/haml/locals.haml +2 -0
  537. data/spec/ramaze/template/haml/with_vars.haml +4 -0
  538. data/spec/ramaze/template/haml.rb +66 -0
  539. data/spec/ramaze/template/liquid/index.liquid +1 -0
  540. data/spec/ramaze/template/liquid/products.liquid +45 -0
  541. data/spec/ramaze/template/liquid.rb +99 -0
  542. data/spec/ramaze/template/markaby/external.mab +8 -0
  543. data/spec/ramaze/template/markaby/sum.mab +1 -0
  544. data/spec/ramaze/template/markaby.rb +61 -0
  545. data/spec/ramaze/template/nagoro/another/long/action.nag +1 -0
  546. data/spec/ramaze/template/nagoro/combined.nag +1 -0
  547. data/spec/ramaze/template/nagoro/file_only.nag +1 -0
  548. data/spec/ramaze/template/nagoro/index.nag +1 -0
  549. data/spec/ramaze/template/nagoro/nested.nag +1 -0
  550. data/spec/ramaze/template/nagoro/some__long__action.nag +1 -0
  551. data/spec/ramaze/template/nagoro/sum.nag +1 -0
  552. data/spec/ramaze/template/nagoro.rb +64 -0
  553. data/spec/ramaze/template/ramaze/external.test +1 -0
  554. data/spec/ramaze/template/redcloth/external.redcloth +1 -0
  555. data/spec/ramaze/template/redcloth.rb +38 -0
  556. data/spec/ramaze/template/remarkably/external.rem +8 -0
  557. data/spec/ramaze/template/remarkably/sum.rem +1 -0
  558. data/spec/ramaze/template/remarkably.rb +58 -0
  559. data/spec/ramaze/template/sass/file.css.sass +5 -0
  560. data/spec/ramaze/template/sass.rb +69 -0
  561. data/spec/ramaze/template/tagz/external.tagz +8 -0
  562. data/spec/ramaze/template/tagz/sum.tagz +1 -0
  563. data/spec/ramaze/template/tagz.rb +62 -0
  564. data/spec/ramaze/template/tenjin/external.tenjin +1 -0
  565. data/spec/ramaze/template/tenjin.rb +47 -0
  566. data/spec/ramaze/template/xslt/concat_words.xsl +16 -0
  567. data/spec/ramaze/template/xslt/index.xsl +14 -0
  568. data/spec/ramaze/template/xslt/products.xsl +32 -0
  569. data/spec/ramaze/template/xslt/ruby_version.xsl +14 -0
  570. data/spec/ramaze/template/xslt.rb +90 -0
  571. data/spec/ramaze/template.rb +128 -0
  572. data/spec/snippets/array/put_within.rb +33 -0
  573. data/spec/snippets/binding/locals.rb +9 -0
  574. data/spec/snippets/divide.rb +19 -0
  575. data/spec/snippets/kernel/constant.rb +23 -0
  576. data/spec/snippets/numeric/filesize_format.rb +12 -0
  577. data/spec/snippets/numeric/time.rb +12 -0
  578. data/spec/snippets/object/__dir__.rb +8 -0
  579. data/spec/snippets/object/acquire.rb +71 -0
  580. data/spec/snippets/ordered_set.rb +63 -0
  581. data/spec/snippets/ramaze/caller_info.rb +39 -0
  582. data/spec/snippets/ramaze/caller_lines.rb +30 -0
  583. data/spec/snippets/string/camel_case.rb +25 -0
  584. data/spec/snippets/string/color.rb +11 -0
  585. data/spec/snippets/string/snake_case.rb +24 -0
  586. data/spec/snippets/string/unindent.rb +43 -0
  587. data/spec/snippets/thread/into.rb +20 -0
  588. metadata +823 -0
@@ -0,0 +1,742 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1 plus MathML 2.0 plus SVG 1.1//EN" "http://www.w3.org/2002/04/xhtml-math-svg/xhtml-math-svg.dtd">
3
+ <html xml:lang="en" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/1999/xhtml">
4
+ <head><meta content="application/xhtml+xml;charset=utf-8" http-equiv="Content-type" /><title>The official Ramaze todolist tutorial</title><style type="text/css">
5
+ pre { margin: 1em; padding: 1em; }
6
+ pre.iplastic .Constant {
7
+ color: #6782D3;
8
+ }
9
+ pre.iplastic .Support {
10
+ font-weight: bold;
11
+ color: #3333FF;
12
+ }
13
+ pre.iplastic .EmbeddedSource {
14
+ background-color: #F9F9F9;
15
+ color: #000000;
16
+ }
17
+ pre.iplastic .Arguments {
18
+ font-style: italic;
19
+ }
20
+ pre.iplastic .TypeName {
21
+ font-weight: bold;
22
+ }
23
+ pre.iplastic .Identifier {
24
+ color: #9700CC;
25
+ }
26
+ pre.iplastic .Number {
27
+ color: #0066FF;
28
+ }
29
+ pre.iplastic .SectionName {
30
+ font-weight: bold;
31
+ }
32
+ pre.iplastic .Storage {
33
+ font-weight: bold;
34
+ }
35
+ pre.iplastic .line-numbers {
36
+ background-color: #BAD6FD;
37
+ color: #000000;
38
+ }
39
+ pre.iplastic {
40
+ background-color: #EEEEEE;
41
+ color: #000000;
42
+ }
43
+ pre.iplastic .FrameTitle {
44
+ font-weight: bold;
45
+ color: #000000;
46
+ }
47
+ pre.iplastic .TagName {
48
+ font-weight: bold;
49
+ }
50
+ pre.iplastic .Tag {
51
+ color: #0033CC;
52
+ }
53
+ pre.iplastic .Exception {
54
+ color: #990000;
55
+ }
56
+ pre.iplastic .XmlDeclaration {
57
+ color: #333333;
58
+ }
59
+ pre.iplastic .TrailingWhitespace {
60
+ background-color: #EEEEEE;
61
+ }
62
+ pre.iplastic .TagAttribute {
63
+ color: #3366CC;
64
+ font-style: italic;
65
+ }
66
+ pre.iplastic .Invalid {
67
+ background-color: #E7342D;
68
+ color: #FF0000;
69
+ }
70
+ pre.iplastic .Keyword {
71
+ color: #0000FF;
72
+ }
73
+ pre.iplastic .String {
74
+ color: #009933;
75
+ }
76
+ pre.iplastic .Comment {
77
+ color: #0066FF;
78
+ font-style: italic;
79
+ }
80
+ pre.iplastic .FunctionName {
81
+ color: #FF8000;
82
+ }
83
+ pre.iplastic .RegularExpression {
84
+ color: #FF0080;
85
+ }
86
+
87
+ </style></head>
88
+ <body>
89
+ <h1 id="todo_list_tutorial">To-do List Tutorial</h1>
90
+ <div class="maruku_toc"><ul style="list-style: none;"><li><a href="#step_zero_introduction">Step Zero, Introduction</a></li><li><a href="#first_step_create">First Step, Create</a></li><li><a href="#second_step_m_like_model">Second Step, M, like Model</a></li><li><a href="#third_step_v_like_view">Third Step, V, like View</a></li><li><a href="#fourth_step_c_like_controller">Fourth Step, C, like Controller</a></li><li><a href="#fifth_step_getting_dynamic">Fifth Step, getting dynamic</a></li><li><a href="#sixth_step_open_and_close_tasks">Sixth Step, open and close tasks</a></li><li><a href="#seventh_step_delete_tasks">Seventh Step, delete tasks</a></li><li><a href="#eighth_step_elements">Eighth Step, Elements</a></li><li><a href="#ninth_step_prettify">Ninth Step, Prettify</a></li><li><a href="#tenth_step_configuration">Tenth Step, Configuration</a></li><li><a href="#eleventh_step_refactor_with_aspecthelper">Eleventh Step, Refactor with AspectHelper</a></li><li><a href="#twelfth_step_validation_and_errors">Twelfth Step, Validation and Errors</a></li></ul></div>
91
+ <h2 id="step_zero_introduction">Step Zero, Introduction</h2>
92
+
93
+ <p>Welcome to our official tutorial, the mandatory to-do list. I&#8217;m writing this while doing the steps to assure it will work for you.</p>
94
+
95
+ <p>The tutorial assumes that you have Ramaze installed already. The easiest way to do that is <code>gem install ramaze</code>, for other ways of installation please see the documentation at http://ramaze.rubyforge.org</p>
96
+
97
+ <p>Should you encounter any problems while doing this tutorial, this might either be because Ramaze changed (which happens very often while it is still young) or I actually made some mistake while writing it.</p>
98
+
99
+ <p>In either case it would make me (and all other poor fellows who happen to try this tutorial) very happy if you could spare some time and report the issue either on the Bug tracker at http://rubyforge.org/projects/ramaze or just drop by on IRC ( irc.freenode.org channel: #ramaze ).</p>
100
+
101
+ <p>There is also a Mailing list available where you can keep yourself updated on what is going on with little effort, it is also located on the project-page at RubyForge.</p>
102
+
103
+ <p>Additionally, we now have added tests for the resulting application that you can find in spec/examples/todolist.rb</p>
104
+
105
+ <p>Date of last update: Thu Jan 31 04:37:16 JST 2008</p>
106
+
107
+ <p>Thanks in advance. The author of the tutorial, Michael &#8216;manveru&#8217; Fellinger</p>
108
+
109
+ <h2 id="first_step_create">First Step, Create</h2>
110
+
111
+ <p>We are using <code>ramaze --create todolist</code> to create a new application. Ramaze will then create the directory and fill it with a skeleton of a quite sophisticated hello-world example out of which we will create the actual to-do list.</p>
112
+
113
+ <p>So run:</p>
114
+
115
+ <pre class="iplastic"><code class="shell-unix-generic" lang="shell-unix-generic">ramaze --create todolist
116
+ </code></pre>
117
+
118
+ <p>done.</p>
119
+
120
+ <h2 id="second_step_m_like_model">Second Step, M, like Model</h2>
121
+
122
+ <p>Ramaze comes at the moment only with a simple wrapper of the YAML::Store. So we are going to base this on the tools available, you can just do the same with your ORM or database-library of choice.</p>
123
+
124
+ <p>So first, create a <code>model/todolist.rb</code> for our application:</p>
125
+
126
+ <pre class="iplastic"><code class="ruby" lang="ruby"><span class="Keyword">require</span> <span class="String"><span class="String">'</span>ramaze/store/default<span class="String">'</span></span>
127
+ TodoList <span class="Keyword">=</span> <span class="Support">Ramaze</span>::<span class="FunctionName">Store</span>::<span class="FunctionName">Default</span>.<span class="FunctionName">new</span>(<span class="String"><span class="String">'</span>todolist.yaml<span class="String">'</span></span>)
128
+ </code></pre>
129
+
130
+ <p>Let&#8217;s add some items as well to have a base to start from.</p>
131
+
132
+ <pre class="iplastic"><code class="ruby" lang="ruby">{ <span class="String"><span class="String">'</span>Laundry<span class="String">'</span></span> =&gt; {<span class="Constant"><span class="Constant">:</span>done</span> =&gt; <span class="Identifier">false</span>},
133
+ <span class="String"><span class="String">'</span>Wash dishes<span class="String">'</span></span> =&gt; {<span class="Constant"><span class="Constant">:</span>done</span> =&gt; <span class="Identifier">false</span>},
134
+ }.<span class="FunctionName">each</span> <span class="Keyword">do </span>|title, value|
135
+ <span class="Support">TodoList</span>[title] <span class="Keyword">=</span> value
136
+ <span class="Keyword">end</span>
137
+ </code></pre>
138
+
139
+ <h2 id="third_step_v_like_view">Third Step, V, like View</h2>
140
+
141
+ <p>Now let&#8217;s get our hands dirty and just edit the templates for our to-do list.</p>
142
+
143
+ <p>Start with editing <code>view/index.xhtml</code>, it is using the default templating of Ramaze, called Ezamar.</p>
144
+
145
+ <p>The index.xhtml currently contains a default welcome page, remove the contents.</p>
146
+
147
+ <p>Let&#8217;s put some things in there, I&#8217;ll explain the syntax as we go, it&#8217;s quite simple.</p>
148
+
149
+ <pre class="iplastic"><code class="html" lang="html"><span class="Tag"><span class="Tag">&lt;</span><span class="TagName">html</span><span class="Tag">&gt;</span></span>
150
+ <span class="Tag"><span class="Tag">&lt;</span><span class="TagName">head</span><span class="Tag">&gt;</span></span>
151
+ <span class="Tag"><span class="Tag">&lt;</span><span class="TagName">title</span><span class="Tag">&gt;</span></span>TodoList<span class="Tag"><span class="Tag">&lt;/</span><span class="TagName">title</span><span class="Tag">&gt;</span></span>
152
+ <span class="Tag"><span class="Tag">&lt;/</span><span class="TagName">head</span><span class="Tag">&gt;</span></span>
153
+ <span class="Tag"><span class="Tag">&lt;</span><span class="TagName">body</span><span class="Tag">&gt;</span></span>
154
+ <span class="Tag"><span class="Tag">&lt;</span><span class="TagName">h1</span><span class="Tag">&gt;</span></span>TodoList<span class="Tag"><span class="Tag">&lt;/</span><span class="TagName">h1</span><span class="Tag">&gt;</span></span>
155
+ <span class="Tag"><span class="Tag">&lt;</span><span class="TagName">ul</span><span class="Tag">&gt;</span></span>
156
+ <span class="EmbeddedSource"> <span class="EmbeddedSource"><span class="EmbeddedSource">&lt;?</span><span class="Constant">r</span></span></span>
157
+ <span class="EmbeddedSource"><span class="EmbeddedSource"> <span class="Constant">TodoList</span><span class="Keyword">.</span><span class="Constant">each</span> <span class="Keyword">do</span> <span class="Keyword">|</span><span class="Constant">title</span>, <span class="Constant">value</span><span class="Keyword">|</span></span></span>
158
+ <span class="EmbeddedSource"><span class="EmbeddedSource"> <span class="Constant">status</span> <span class="Keyword">=</span> <span class="Constant">value</span>[:<span class="Constant">done</span>] ? <span class="String"><span class="String">'</span><span class="String">done</span><span class="String">'</span></span> : <span class="String"><span class="String">'</span><span class="String">not done</span><span class="String">'</span></span></span></span>
159
+ <span class="EmbeddedSource"><span class="EmbeddedSource"> <span class="EmbeddedSource"><span class="EmbeddedSource">?</span>&gt;</span></span></span>
160
+ <span class="Tag"><span class="Tag">&lt;</span><span class="TagName">li</span><span class="Tag">&gt;</span></span>#<span class="EmbeddedSource">{h title}</span>: #<span class="EmbeddedSource">{status}</span><span class="Tag"><span class="Tag">&lt;/</span><span class="TagName">li</span><span class="Tag">&gt;</span></span>
161
+ <span class="EmbeddedSource"><span class="EmbeddedSource">&lt;?r</span> <span class="Keyword">end</span> <span class="EmbeddedSource">?&gt;</span></span>
162
+ <span class="Tag"><span class="Tag">&lt;/</span><span class="TagName">ul</span><span class="Tag">&gt;</span></span>
163
+ <span class="Tag"><span class="Tag">&lt;/</span><span class="TagName">body</span><span class="Tag">&gt;</span></span>
164
+ <span class="Tag"><span class="Tag">&lt;/</span><span class="TagName">html</span><span class="Tag">&gt;</span></span>
165
+ </code></pre>
166
+
167
+ <p>I will assume that you are familiar with basic Ruby already, so we will concentrate on the things new here.</p>
168
+
169
+ <p><code>&lt;?r ?&gt;</code> defines an area of ruby-code. Later, when the template is transformed into pure Ruby it will be evaluated. We iterate over the TodoList model and pass the title and value into a block. In that block we can just get the values of title and status (which we define based on the value) displayed on the page.</p>
170
+
171
+ <p>The whole Template would expand to something like this (only showing the interesting part)</p>
172
+
173
+ <pre class="iplastic"><code class="html" lang="html"><span class="Tag"><span class="Tag">&lt;</span><span class="TagName">ul</span><span class="Tag">&gt;</span></span>
174
+ <span class="Tag"><span class="Tag">&lt;</span><span class="TagName">li</span><span class="Tag">&gt;</span></span>Laundry: not done<span class="Tag"><span class="Tag">&lt;/</span><span class="TagName">li</span><span class="Tag">&gt;</span></span>
175
+ <span class="Tag"><span class="Tag">&lt;</span><span class="TagName">li</span><span class="Tag">&gt;</span></span>Wash dishes: not done<span class="Tag"><span class="Tag">&lt;/</span><span class="TagName">li</span><span class="Tag">&gt;</span></span>
176
+ <span class="Tag"><span class="Tag">&lt;/</span><span class="TagName">ul</span><span class="Tag">&gt;</span></span>
177
+ </code></pre>
178
+
179
+ <p>That wasn&#8217;t too bad, huh?</p>
180
+
181
+ <p>Now, so we can get our instant pleasure of seeing the result of our (hard) work, let&#8217;s see how to start ramaze.</p>
182
+
183
+ <p>In the <code>todolist</code> directory run <code>ramaze</code>.</p>
184
+
185
+ <p>This will start an instance of Ramaze and run your application on it. You can now access it by browsing to http://localhost:7000/</p>
186
+
187
+ <p>7000 is the default-port Ramaze will run on, to change it you can just run <code>ramaze -p 7070</code> or similar. Also be sure to look at the output of <code>ramaze --help</code> to see some other options.</p>
188
+
189
+ <h2 id="fourth_step_c_like_controller">Fourth Step, C, like Controller</h2>
190
+
191
+ <p>The last part of the MVC-paradigm is the Controller.</p>
192
+
193
+ <p>Wouldn&#8217;t it be nice to have a way to add and remove items on our to-do list? Editing the model every time would be quite tiresome and limited.</p>
194
+
195
+ <p>Well, come along, I&#8217;ll introduce you to Controller.</p>
196
+
197
+ <p>In the way MVC is structured, the Controller provides the data in a nice way for the View, removing all of the data-preparation and most of the logic from the templates. This makes it firstly simple to change the front end of your application and secondly provides excellent ways of changing the complete Structure of the Model or View independent from each other.</p>
198
+
199
+ <p>OK, enough of the theory, you will see the benefits in an instant. Go on and edit the file <code>controller/main.rb</code>.</p>
200
+
201
+ <p>The contents of it are like following:</p>
202
+
203
+ <pre class="iplastic"><code class="ruby" lang="ruby"><span class="Keyword">class</span> <span class="TypeName">MainController<span class="TypeName"> <span class="TypeName">&lt;</span> Controller</span></span>
204
+ <span class="Keyword">def</span> <span class="FunctionName">index</span>
205
+ @welcome <span class="Keyword">=</span> <span class="String"><span class="String">&quot;</span>Welcome to Ramaze!<span class="String">&quot;</span></span>
206
+ <span class="Keyword">end</span>
207
+
208
+ <span class="Keyword">def</span> <span class="FunctionName">notemplate</span>
209
+ <span class="String"><span class="String">&quot;</span>there is no template associated with this action<span class="String">&quot;</span></span>
210
+ <span class="Keyword">end</span>
211
+ <span class="Keyword">end</span>
212
+ </code></pre>
213
+
214
+ <p>The only methods right now are <code>#index</code> and <code>#notemplate</code>. The relationship between the methods on the controller and the templates is 1:1, so the method <code>#index</code> is combined with the template <code>index.xhtml</code>. This combination is called an <code>action</code>.</p>
215
+
216
+ <p>Let&#8217;s get back to editing and change the method <code>#index</code> to this:</p>
217
+
218
+ <pre class="iplastic"><code class="ruby" lang="ruby"><span class="Keyword">def</span> <span class="FunctionName">index</span>
219
+ @tasks <span class="Keyword">=</span> <span class="Support">TodoList</span>.<span class="FunctionName">original</span>
220
+ @tasks.<span class="FunctionName">each</span> <span class="Keyword">do </span>|title, value|
221
+ status <span class="Keyword">=</span> value[<span class="Constant"><span class="Constant">:</span>done</span>] <span class="Keyword">?</span> <span class="String"><span class="String">'</span>done<span class="String">'</span></span> : <span class="String"><span class="String">'</span>not done<span class="String">'</span></span>
222
+ @tasks[title] <span class="Keyword">=</span> status
223
+ <span class="Keyword">end</span>
224
+ <span class="Keyword">end</span>
225
+ </code></pre>
226
+
227
+ <p>This will take care of the logic inside the template, which now should be changed to do following:</p>
228
+
229
+ <pre class="iplastic"><code class="ezamar" lang="ezamar"><span class="Tag"><span class="Tag">&lt;</span><span class="TagName">html</span><span class="Tag">&gt;</span></span>
230
+ <span class="Tag"><span class="Tag">&lt;</span><span class="TagName">head</span><span class="Tag">&gt;</span></span>
231
+ <span class="Tag"><span class="Tag">&lt;</span><span class="TagName">title</span><span class="Tag">&gt;</span></span>TodoList<span class="Tag"><span class="Tag">&lt;/</span><span class="TagName">title</span><span class="Tag">&gt;</span></span>
232
+ <span class="Tag"><span class="Tag">&lt;/</span><span class="TagName">head</span><span class="Tag">&gt;</span></span>
233
+ <span class="Tag"><span class="Tag">&lt;</span><span class="TagName">body</span><span class="Tag">&gt;</span></span>
234
+ <span class="Tag"><span class="Tag">&lt;</span><span class="TagName">h1</span><span class="Tag">&gt;</span></span>TodoList<span class="Tag"><span class="Tag">&lt;/</span><span class="TagName">h1</span><span class="Tag">&gt;</span></span>
235
+ <span class="EmbeddedSource"><span class="EmbeddedSource">&lt;?r</span> <span class="Keyword">if</span> <span class="EmbeddedSource"><span class="EmbeddedSource">@</span>tasks</span><span class="EmbeddedSource"><span class="EmbeddedSource">.</span><span class="FunctionName">empty?</span></span> <span class="EmbeddedSource">?&gt;</span></span>
236
+ No Tasks
237
+ <span class="EmbeddedSource"><span class="EmbeddedSource">&lt;?r</span> <span class="Keyword">else</span> <span class="EmbeddedSource">?&gt;</span></span>
238
+ <span class="Tag"><span class="Tag">&lt;</span><span class="TagName">ul</span><span class="Tag">&gt;</span></span>
239
+ <span class="EmbeddedSource"><span class="EmbeddedSource">&lt;?r</span> <span class="EmbeddedSource"><span class="EmbeddedSource">@</span>tasks</span><span class="EmbeddedSource"><span class="EmbeddedSource">.</span><span class="FunctionName">each</span></span> <span class="Keyword">do </span><span class="EmbeddedSource">|</span><span class="EmbeddedSource">title</span><span class="EmbeddedSource">,</span> <span class="EmbeddedSource">status</span><span class="EmbeddedSource">|</span> <span class="EmbeddedSource">?&gt;</span></span>
240
+ <span class="Tag"><span class="Tag">&lt;</span><span class="TagName">li</span><span class="Tag">&gt;</span></span>#<span class="EmbeddedSource">{h title}</span>: #<span class="EmbeddedSource">{status}</span><span class="Tag"><span class="Tag">&lt;/</span><span class="TagName">li</span><span class="Tag">&gt;</span></span>
241
+ <span class="EmbeddedSource"><span class="EmbeddedSource">&lt;?r</span> <span class="Keyword">end</span> <span class="EmbeddedSource">?&gt;</span></span>
242
+ <span class="Tag"><span class="Tag">&lt;/</span><span class="TagName">ul</span><span class="Tag">&gt;</span></span>
243
+ <span class="EmbeddedSource"><span class="EmbeddedSource">&lt;?r</span> <span class="Keyword">end</span> <span class="EmbeddedSource">?&gt;</span></span>
244
+ <span class="Tag"><span class="Tag">&lt;/</span><span class="TagName">body</span><span class="Tag">&gt;</span></span>
245
+ <span class="Tag"><span class="Tag">&lt;/</span><span class="TagName">html</span><span class="Tag">&gt;</span></span>
246
+ </code></pre>
247
+
248
+ <p>The rest of the template can stay the same.</p>
249
+
250
+ <p>Now, if you browse to http://localhost:7000/ again you will not notice any change, which is how it should be. The only change is that if there are no Tasks it will say so.</p>
251
+
252
+ <p>Some things you should know:</p>
253
+
254
+ <ul>
255
+ <li>Instance-variables defined in the Controller are available in the View.</li>
256
+
257
+ <li>The return-value of the Controller does not matter if a template is present.</li>
258
+ </ul>
259
+
260
+ <h2 id="fifth_step_getting_dynamic">Fifth Step, getting dynamic</h2>
261
+
262
+ <p>We set out to build the ultimate to-do list, but there are still some things missing. First off, we want to add new tasks, so let&#8217;s get that done.</p>
263
+
264
+ <p>Add a link on the <code>view/index.xhtml</code> like this:</p>
265
+
266
+ <pre class="iplastic"><code class="ezamar" lang="ezamar"><span class="Tag"><span class="Tag">&lt;</span><span class="TagName">h1</span><span class="Tag">&gt;</span></span>TodoList<span class="Tag"><span class="Tag">&lt;/</span><span class="TagName">h1</span><span class="Tag">&gt;</span></span>
267
+ <span class="Tag"><span class="Tag">&lt;</span><span class="TagName">a</span> <span class="TagAttribute">href</span>=<span class="String"><span class="String">&quot;</span>/new<span class="String">&quot;</span></span><span class="Tag">&gt;</span></span>New Task<span class="Tag"><span class="Tag">&lt;/</span><span class="TagName">a</span><span class="Tag">&gt;</span></span>
268
+ </code></pre>
269
+
270
+ <p>Open a new file <code>view/new.xhtml</code> with a form to add a new task.</p>
271
+
272
+ <pre class="iplastic"><code class="ezamar" lang="ezamar"><span class="Tag"><span class="Tag">&lt;</span><span class="TagName">html</span><span class="Tag">&gt;</span></span>
273
+ <span class="Tag"><span class="Tag">&lt;</span><span class="TagName">head</span><span class="Tag">&gt;</span></span>
274
+ <span class="Tag"><span class="Tag">&lt;</span><span class="TagName">title</span><span class="Tag">&gt;</span></span>TodoList<span class="Tag"><span class="Tag">&lt;/</span><span class="TagName">title</span><span class="Tag">&gt;</span></span>
275
+ <span class="Tag"><span class="Tag">&lt;/</span><span class="TagName">head</span><span class="Tag">&gt;</span></span>
276
+ <span class="Tag"><span class="Tag">&lt;</span><span class="TagName">body</span><span class="Tag">&gt;</span></span>
277
+ <span class="Tag"><span class="Tag">&lt;</span><span class="TagName">h1</span><span class="Tag">&gt;</span></span>New Task<span class="Tag"><span class="Tag">&lt;/</span><span class="TagName">h1</span><span class="Tag">&gt;</span></span>
278
+ <span class="Tag"><span class="Tag">&lt;</span><span class="TagName">a</span> <span class="TagAttribute">href</span>=<span class="String"><span class="String">&quot;</span>/<span class="String">&quot;</span></span><span class="Tag">&gt;</span></span>Back to TodoList<span class="Tag"><span class="Tag">&lt;/</span><span class="TagName">a</span><span class="Tag">&gt;</span></span>
279
+ <span class="Tag"><span class="Tag">&lt;</span><span class="TagName">form</span> <span class="TagAttribute">method</span>=<span class="String"><span class="String">&quot;</span>POST<span class="String">&quot;</span></span> <span class="TagAttribute">action</span>=<span class="String"><span class="String">&quot;</span>create<span class="String">&quot;</span></span><span class="Tag">&gt;</span></span>
280
+ Task: <span class="Tag"><span class="Tag">&lt;</span><span class="TagName">input</span> <span class="TagAttribute">type</span>=<span class="String"><span class="String">&quot;</span>text<span class="String">&quot;</span></span> <span class="TagAttribute">name</span>=<span class="String"><span class="String">&quot;</span>title<span class="String">&quot;</span></span> /<span class="Tag">&gt;</span></span><span class="Tag"><span class="Tag">&lt;</span><span class="TagName">br</span> /<span class="Tag">&gt;</span></span>
281
+ <span class="Tag"><span class="Tag">&lt;</span><span class="TagName">input</span> <span class="TagAttribute">type</span>=<span class="String"><span class="String">&quot;</span>submit<span class="String">&quot;</span></span> /<span class="Tag">&gt;</span></span>
282
+ <span class="Tag"><span class="Tag">&lt;/</span><span class="TagName">form</span><span class="Tag">&gt;</span></span>
283
+ <span class="Tag"><span class="Tag">&lt;/</span><span class="TagName">body</span><span class="Tag">&gt;</span></span>
284
+ <span class="Tag"><span class="Tag">&lt;/</span><span class="TagName">html</span><span class="Tag">&gt;</span></span>
285
+ </code></pre>
286
+
287
+ <p>We will not need a method for this on our controller, in fact, actions can consist of either method and template or only one of them. The Controller can act as a View and the View can work like you may know it from PHP.</p>
288
+
289
+ <p>If you try to use this form you will notice that we have not yet defined a way to actually create the task.</p>
290
+
291
+ <p>You will get the default Ramaze error-page instead. Please take your time to explore it and see how Ramaze reacted on the error.</p>
292
+
293
+ <p>It will show you the back trace and what state the application is in at the moment, the request and response and the contents of the session. This is very useful for debugging and development, you can provide your own set of error-pages before going into production (or deactivate them fully) though.</p>
294
+
295
+ <p>OK, let&#8217;s implement the action for <code>#create</code>, all we want to do is take the requests parameters and create a new task for it, this looks like following on your MainController.</p>
296
+
297
+ <pre class="iplastic"><code class="ruby" lang="ruby"><span class="Keyword">def</span> <span class="FunctionName">create</span>
298
+ title <span class="Keyword">=</span> request[<span class="String"><span class="String">'</span>title<span class="String">'</span></span>]
299
+ <span class="Support">TodoList</span>[title] <span class="Keyword">=</span> {<span class="Constant"><span class="Constant">:</span>done</span> =&gt; <span class="Identifier">false</span>}
300
+ redirect Rs()
301
+ <span class="Keyword">end</span>
302
+ </code></pre>
303
+
304
+ <p>That&#8217;s all folks!</p>
305
+
306
+ <p>We get the title from the request-object, put it into our TodoList as undone and redirect back to the mapping of the current Controller (&#8217;/&#8217; in this case).</p>
307
+
308
+ <p>Now you can create as many tasks as you want, please don&#8217;t get overworked ;)</p>
309
+
310
+ <h2 id="sixth_step_open_and_close_tasks">Sixth Step, open and close tasks</h2>
311
+
312
+ <p>Since the nature of tasks is to be done eventually we will need some way to mark it as done or open tasks again.</p>
313
+
314
+ <p>Jump into <code>view/index.xhtml</code> and do the following:</p>
315
+
316
+ <pre class="iplastic"><code class="ezamar" lang="ezamar"><span class="EmbeddedSource"><span class="EmbeddedSource">&lt;?r</span> <span class="EmbeddedSource"><span class="EmbeddedSource">@</span>tasks</span><span class="EmbeddedSource"><span class="EmbeddedSource">.</span><span class="FunctionName">each</span></span> <span class="Keyword">do </span><span class="EmbeddedSource">|</span><span class="EmbeddedSource">title</span><span class="EmbeddedSource">,</span> <span class="EmbeddedSource">status</span><span class="EmbeddedSource">,</span> <span class="EmbeddedSource">toggle</span><span class="EmbeddedSource">|</span> <span class="EmbeddedSource">?&gt;</span></span>
317
+ <span class="Tag"><span class="Tag">&lt;</span><span class="TagName">li</span><span class="Tag">&gt;</span></span>
318
+ #<span class="EmbeddedSource">{h title}</span>: #<span class="EmbeddedSource">{status}</span> - [ #<span class="EmbeddedSource">{toggle}</span> ]
319
+ <span class="Tag"><span class="Tag">&lt;/</span><span class="TagName">li</span><span class="Tag">&gt;</span></span>
320
+ <span class="EmbeddedSource"><span class="EmbeddedSource">&lt;?r</span> <span class="Keyword">end</span></span>
321
+ </code></pre>
322
+
323
+ <p>We added a new element here, <code>toggle</code>, the Controller should give us a link to change the status corresponding to the status of the task, so off we go and change the index method on the controller once again:</p>
324
+
325
+ <pre class="iplastic"><code class="ruby" lang="ruby"><span class="Keyword">def</span> <span class="FunctionName">index</span>
326
+ @tasks <span class="Keyword">=</span> []
327
+ <span class="Support">TodoList</span>.<span class="FunctionName">original</span>.<span class="FunctionName">each</span> <span class="Keyword">do </span>|title, value|
328
+ <span class="Keyword">if</span> value[<span class="Constant"><span class="Constant">:</span>done</span>]
329
+ status <span class="Keyword">=</span> <span class="String"><span class="String">'</span>done<span class="String">'</span></span>
330
+ toggle <span class="Keyword">=</span> A(<span class="String"><span class="String">'</span>Open Task<span class="String">'</span></span>, <span class="Constant"><span class="Constant">:</span>href</span> =&gt; Rs(<span class="Constant"><span class="Constant">:</span>open</span>, title))
331
+ <span class="Keyword">else</span>
332
+ status <span class="Keyword">=</span> <span class="String"><span class="String">'</span>not done<span class="String">'</span></span>
333
+ toggle <span class="Keyword">=</span> A(<span class="String"><span class="String">'</span>Close Task<span class="String">'</span></span>, <span class="Constant"><span class="Constant">:</span>href</span> =&gt; Rs(<span class="Constant"><span class="Constant">:</span>close</span>, title))
334
+ <span class="Keyword">end</span>
335
+ @tasks <span class="Keyword">&lt;&lt;</span> [title, status, toggle]
336
+ <span class="Keyword">end</span>
337
+ @tasks.<span class="FunctionName">sort!</span>
338
+ <span class="Keyword">end</span>
339
+ </code></pre>
340
+
341
+ <p>Wow, quite some new stuff here. Let me explain that in detail.</p>
342
+
343
+ <p>We first decide whether a task is done or not, then go on and provide a link to toggle the status, A and Rs are both methods that help you do that. The result will be something like:</p>
344
+
345
+ <pre class="iplastic"><code class="ezamar" lang="ezamar"><span class="Tag"><span class="Tag">&lt;</span><span class="TagName">a</span> <span class="TagAttribute">href</span>=<span class="String"><span class="String">&quot;</span>/open/Wash+dishes<span class="String">&quot;</span></span><span class="Tag">&gt;</span></span>Close Task<span class="Tag"><span class="Tag">&lt;/</span><span class="TagName">a</span><span class="Tag">&gt;</span></span>
346
+ </code></pre>
347
+
348
+ <p>Rs actually is responsible to build the links href, for more information please take a look at the RDoc for LinkHelper.</p>
349
+
350
+ <p>Also, you might have noticed that the tasks were changing order on every reload, which is because we were using an Hash, which are per definition unsorted, so now we use an array to hold our tasks and sort it.</p>
351
+
352
+ <p>As usual since the links for open and close don&#8217;t lead anywhere, add the corresponding methods to the Controller:</p>
353
+
354
+ <pre class="iplastic"><code class="ruby" lang="ruby"><span class="Keyword">def</span> <span class="FunctionName">open</span> title
355
+ task_status title, <span class="Identifier">false</span>
356
+ redirect Rs()
357
+ <span class="Keyword">end</span>
358
+
359
+ <span class="Keyword">def</span> <span class="FunctionName">close</span> title
360
+ task_status title, <span class="Identifier">true</span>
361
+ redirect Rs()
362
+ <span class="Keyword">end</span>
363
+
364
+ <span class="Keyword">private</span>
365
+
366
+ <span class="Keyword">def</span> <span class="FunctionName">task_status</span> title, status
367
+ task <span class="Keyword">=</span> <span class="Support">TodoList</span>[title]
368
+ task[<span class="Constant"><span class="Constant">:</span>done</span>] <span class="Keyword">=</span> status
369
+ <span class="Support">TodoList</span>[title] <span class="Keyword">=</span> task
370
+ <span class="Keyword">end</span>
371
+ </code></pre>
372
+
373
+ <p>Oh, now what have we got here? <code>private</code> declares that methods from here on are only to be used within the Controller itself, we define an <code>#task_status</code> method that takes the title and status to be set so we don&#8217;t have to repeat that code in <code>#open</code> and <code>#close</code> and follow the DRY (Don&#8217;t repeat yourself) paradigm.</p>
374
+
375
+ <p>Another thing we have not encountered so far is that you can define your public methods to take parameters on their own, they will be calculated from requests.</p>
376
+
377
+ <pre class="iplastic"><code class="ruby" lang="ruby"><span class="String"><span class="String">'</span>/open/Wash+dishes<span class="String">'</span></span>
378
+ </code></pre>
379
+
380
+ <p>will translate into:</p>
381
+
382
+ <pre class="iplastic"><code class="ruby" lang="ruby"><span class="FunctionName">open</span>(<span class="String"><span class="String">'</span>Wash dishes<span class="String">'</span></span>)
383
+ </code></pre>
384
+
385
+ <p>Which in turn will call</p>
386
+
387
+ <pre class="iplastic"><code class="ruby" lang="ruby"><span class="FunctionName">task_status</span>(<span class="String"><span class="String">'</span>Wash dishes<span class="String">'</span></span>, <span class="Identifier">false</span>)
388
+ </code></pre>
389
+
390
+ <p>That&#8217;s it, go on and try it :)</p>
391
+
392
+ <h2 id="seventh_step_delete_tasks">Seventh Step, delete tasks</h2>
393
+
394
+ <p>Well, creating, opening and closing work now, one of the things you will consider is to delete a task permanently.</p>
395
+
396
+ <p>This is just two little changes away, so let&#8217;s add the link for deletion in our Controller:</p>
397
+
398
+ <pre class="iplastic"><code class="ruby" lang="ruby">delete <span class="Keyword">=</span> A(<span class="String"><span class="String">'</span>Delete<span class="String">'</span></span>, <span class="Constant"><span class="Constant">:</span>href</span> =&gt; Rs(<span class="Constant"><span class="Constant">:</span>delete</span>, title))
399
+ @tasks <span class="Keyword">&lt;&lt;</span> [title, status, toggle, delete]
400
+ </code></pre>
401
+
402
+ <p>and an corresponding method while we&#8217;re at it:</p>
403
+
404
+ <pre class="iplastic"><code class="ruby" lang="ruby"><span class="Keyword">def</span> <span class="FunctionName">delete</span> title
405
+ <span class="Support">TodoList</span>.<span class="FunctionName">delete</span> title
406
+ redirect Rs()
407
+ <span class="Keyword">end</span>
408
+ </code></pre>
409
+
410
+ <p>Now jumping to <code>view/index.xhtml</code> again, change it so it shows the link:</p>
411
+
412
+ <pre class="iplastic"><code class="ezamar" lang="ezamar"><span class="EmbeddedSource"><span class="EmbeddedSource">&lt;?r</span> <span class="EmbeddedSource"><span class="EmbeddedSource">@</span>tasks</span><span class="EmbeddedSource"><span class="EmbeddedSource">.</span><span class="FunctionName">each</span></span> <span class="Keyword">do </span><span class="EmbeddedSource">|</span><span class="EmbeddedSource">title</span><span class="EmbeddedSource">,</span> <span class="EmbeddedSource">status</span><span class="EmbeddedSource">,</span> <span class="EmbeddedSource">toggle</span><span class="EmbeddedSource">,</span> <span class="EmbeddedSource">delete</span><span class="EmbeddedSource">|</span> <span class="EmbeddedSource">?&gt;</span></span>
413
+ <span class="Tag"><span class="Tag">&lt;</span><span class="TagName">li</span><span class="Tag">&gt;</span></span>
414
+ #<span class="EmbeddedSource">{h title}</span>: #<span class="EmbeddedSource">{status}</span> [ #<span class="EmbeddedSource">{toggle}</span> | #<span class="EmbeddedSource">{delete}</span> ]
415
+ <span class="Tag"><span class="Tag">&lt;/</span><span class="TagName">li</span><span class="Tag">&gt;</span></span>
416
+ <span class="EmbeddedSource"><span class="EmbeddedSource">&lt;?r</span> <span class="Keyword">end</span> <span class="EmbeddedSource">?&gt;</span></span>
417
+ </code></pre>
418
+
419
+ <p>Voilà, you now have acquired the Certificate of Ramazeness.</p>
420
+
421
+ <p>Just kidding, but that really are the basics, in the next few steps I will explain some more advanced concepts of Ramaze and Ezamar.</p>
422
+
423
+ <h2 id="eighth_step_elements">Eighth Step, Elements</h2>
424
+
425
+ <pre class="iplastic"><code class="ezamar" lang="ezamar"><span class="Tag"><span class="Tag">&lt;</span><span class="TagName">Page</span><span class="Tag">&gt;<span class="Tag">&lt;</span>/</span><span class="TagName">Page</span><span class="Tag">&gt;</span></span>
426
+ </code></pre>
427
+
428
+ <p>This is called an Element, Ramaze will go and search for a class that matches the name Page and responds to <code>#render</code>. Then it will go and hand the content in between to that Element.</p>
429
+
430
+ <p>Sounds weird?</p>
431
+
432
+ <p>Let us have a look at our templates, they got some repetitive stuff, like:</p>
433
+
434
+ <pre class="iplastic"><code class="ezamar" lang="ezamar"><span class="Tag"><span class="Tag">&lt;</span><span class="TagName">html</span><span class="Tag">&gt;</span></span>
435
+ <span class="Tag"><span class="Tag">&lt;</span><span class="TagName">head</span><span class="Tag">&gt;</span></span>
436
+ <span class="Tag"><span class="Tag">&lt;</span><span class="TagName">title</span><span class="Tag">&gt;</span></span>TodoList<span class="Tag"><span class="Tag">&lt;/</span><span class="TagName">title</span><span class="Tag">&gt;</span></span>
437
+ <span class="Tag"><span class="Tag">&lt;/</span><span class="TagName">head</span><span class="Tag">&gt;</span></span>
438
+ <span class="Tag"><span class="Tag">&lt;</span><span class="TagName">body</span><span class="Tag">&gt;</span></span>
439
+ <span class="Tag"><span class="Tag">&lt;</span><span class="TagName">h1</span><span class="Tag">&gt;</span></span>some title<span class="Tag"><span class="Tag">&lt;/</span><span class="TagName">h1</span><span class="Tag">&gt;</span></span>
440
+ <span class="Tag"><span class="Tag">&lt;/</span><span class="TagName">body</span><span class="Tag">&gt;</span></span>
441
+ <span class="Tag"><span class="Tag">&lt;/</span><span class="TagName">html</span><span class="Tag">&gt;</span></span>
442
+ </code></pre>
443
+
444
+ <p>How about replacing that with something short and reusable:</p>
445
+
446
+ <pre class="iplastic"><code class="html" lang="html"><span class="Tag"><span class="Tag">&lt;</span><span class="TagName">Page</span> <span class="TagAttribute">title</span>=<span class="String"><span class="String">&quot;</span>TodoList<span class="String">&quot;</span></span><span class="Tag">&gt;</span></span>
447
+ your other content
448
+ <span class="Tag"><span class="Tag">&lt;/</span><span class="TagName">Page</span><span class="Tag">&gt;</span></span>
449
+ </code></pre>
450
+
451
+ <p>Would be nice of course, and when you start having more templates it makes an awful lot of sense being able to change the enclosing stuff in one place.</p>
452
+
453
+ <p>So let&#8217;s apply DRY here as well.</p>
454
+
455
+ <p>Take a look at the <code>src/element/page.rb</code></p>
456
+
457
+ <pre class="iplastic"><code class="ruby" lang="ruby"><span class="Keyword">class</span> <span class="TypeName">Page<span class="TypeName"> <span class="TypeName">&lt;</span> Ezamar::Element</span></span>
458
+ <span class="Keyword">def</span> <span class="FunctionName">render</span>
459
+ <span class="String"><span class="String">%{</span></span>
460
+ <span class="String"> &lt;html&gt;</span>
461
+ <span class="String"> &lt;head&gt;</span>
462
+ <span class="String"> &lt;title&gt;Welcome to Ramaze&lt;/title&gt;</span>
463
+ <span class="String"> &lt;/head&gt;</span>
464
+ <span class="String"> &lt;body&gt;</span>
465
+ <span class="String"> <span class="String"><span class="String">#{</span>content<span class="String">}</span></span></span>
466
+ <span class="String"> &lt;/body&gt;</span>
467
+ <span class="String"> &lt;/html&gt;</span>
468
+ <span class="String"> <span class="String">}</span></span>
469
+ <span class="Keyword">end</span>
470
+ <span class="Keyword">end</span>
471
+ </code></pre>
472
+
473
+ <p>Alright, most things we need are in place already, the most important thing is the <code>#content</code> method that we call with <code>#{content}</code> inside the string in <code>#render</code>.</p>
474
+
475
+ <p>Just adopt it to your liking, I&#8217;ll just use the things we had in our templates so far:</p>
476
+
477
+ <pre class="iplastic"><code class="ruby" lang="ruby"><span class="Keyword">class</span> <span class="TypeName">Page<span class="TypeName"> <span class="TypeName">&lt;</span> Ezamar::Element</span></span>
478
+ <span class="Keyword">def</span> <span class="FunctionName">render</span>
479
+ <span class="String"><span class="String">%{</span></span>
480
+ <span class="String"> &lt;html&gt;</span>
481
+ <span class="String"> &lt;head&gt;</span>
482
+ <span class="String"> &lt;title&gt;TodoList&lt;/title&gt;</span>
483
+ <span class="String"> &lt;/head&gt;</span>
484
+ <span class="String"> &lt;body&gt;</span>
485
+ <span class="String"> &lt;h1&gt;<span class="String"><span class="String">#{</span><span class="String"><span class="String">@</span>title</span><span class="String">}</span></span>&lt;/h1&gt;</span>
486
+ <span class="String"> <span class="String"><span class="String">#{</span>content<span class="String">}</span></span></span>
487
+ <span class="String"> &lt;/body&gt;</span>
488
+ <span class="String"> &lt;/html&gt;</span>
489
+ <span class="String"> <span class="String">}</span></span>
490
+ <span class="Keyword">end</span>
491
+ <span class="Keyword">end</span>
492
+ </code></pre>
493
+
494
+ <p>Please note that instance variables reflecting the parameters are set.</p>
495
+
496
+ <p>And let&#8217;s change our templates as well.</p>
497
+
498
+ <p>First the <code>view/index.xhtml</code></p>
499
+
500
+ <pre class="iplastic"><code class="ezamar" lang="ezamar"><span class="Tag"><span class="Tag">&lt;</span><span class="TagName">Page</span> <span class="TagAttribute">title</span>=<span class="String"><span class="String">&quot;</span>TodoList<span class="String">&quot;</span></span><span class="Tag">&gt;</span></span>
501
+ <span class="Tag"><span class="Tag">&lt;</span><span class="TagName">a</span> <span class="TagAttribute">href</span>=<span class="String"><span class="String">&quot;</span>/new<span class="String">&quot;</span></span><span class="Tag">&gt;</span></span>New Task<span class="Tag"><span class="Tag">&lt;/</span><span class="TagName">a</span><span class="Tag">&gt;</span></span>
502
+ <span class="EmbeddedSource"><span class="EmbeddedSource">&lt;?r</span> <span class="Keyword">if</span> <span class="EmbeddedSource"><span class="EmbeddedSource">@</span>tasks</span><span class="EmbeddedSource"><span class="EmbeddedSource">.</span><span class="FunctionName">empty?</span></span> <span class="EmbeddedSource">?&gt;</span></span>
503
+ No Tasks
504
+ <span class="EmbeddedSource"><span class="EmbeddedSource">&lt;?r</span> <span class="Keyword">else</span> <span class="EmbeddedSource">?&gt;</span></span>
505
+ <span class="Tag"><span class="Tag">&lt;</span><span class="TagName">ul</span><span class="Tag">&gt;</span></span>
506
+ <span class="EmbeddedSource"><span class="EmbeddedSource">&lt;?r</span> <span class="EmbeddedSource"><span class="EmbeddedSource">@</span>tasks</span><span class="EmbeddedSource"><span class="EmbeddedSource">.</span><span class="FunctionName">each</span></span> <span class="Keyword">do </span><span class="EmbeddedSource">|</span><span class="EmbeddedSource">title</span><span class="EmbeddedSource">,</span> <span class="EmbeddedSource">status</span><span class="EmbeddedSource">,</span> <span class="EmbeddedSource">toggle</span><span class="EmbeddedSource">,</span> <span class="EmbeddedSource">delete</span><span class="EmbeddedSource">|</span> <span class="EmbeddedSource">?&gt;</span></span>
507
+ <span class="Tag"><span class="Tag">&lt;</span><span class="TagName">li</span><span class="Tag">&gt;</span></span>
508
+ #<span class="EmbeddedSource">{h title}</span>: #<span class="EmbeddedSource">{status}</span> [ #<span class="EmbeddedSource">{toggle}</span> | #<span class="EmbeddedSource">{delete}</span> ]
509
+ <span class="Tag"><span class="Tag">&lt;/</span><span class="TagName">li</span><span class="Tag">&gt;</span></span>
510
+ <span class="EmbeddedSource"><span class="EmbeddedSource">&lt;?r</span> <span class="Keyword">end</span> <span class="EmbeddedSource">?&gt;</span></span>
511
+ <span class="Tag"><span class="Tag">&lt;/</span><span class="TagName">ul</span><span class="Tag">&gt;</span></span>
512
+ <span class="EmbeddedSource"><span class="EmbeddedSource">&lt;?r</span> <span class="Keyword">end</span> <span class="EmbeddedSource">?&gt;</span></span>
513
+ <span class="Tag"><span class="Tag">&lt;/</span><span class="TagName">Page</span><span class="Tag">&gt;</span></span>
514
+ </code></pre>
515
+
516
+ <p>and the <code>view/new.xhtml</code></p>
517
+
518
+ <pre class="iplastic"><code class="ezamar" lang="ezamar"><span class="Tag"><span class="Tag">&lt;</span><span class="TagName">Page</span> <span class="TagAttribute">title</span>=<span class="String"><span class="String">&quot;</span>New Task<span class="String">&quot;</span></span><span class="Tag">&gt;</span></span>
519
+ <span class="Tag"><span class="Tag">&lt;</span><span class="TagName">a</span> <span class="TagAttribute">href</span>=<span class="String"><span class="String">&quot;</span>/<span class="String">&quot;</span></span><span class="Tag">&gt;</span></span>Back to TodoList<span class="Tag"><span class="Tag">&lt;/</span><span class="TagName">a</span><span class="Tag">&gt;</span></span>
520
+ <span class="Tag"><span class="Tag">&lt;</span><span class="TagName">form</span> <span class="TagAttribute">method</span>=<span class="String"><span class="String">&quot;</span>POST<span class="String">&quot;</span></span> <span class="TagAttribute">action</span>=<span class="String"><span class="String">&quot;</span>create<span class="String">&quot;</span></span><span class="Tag">&gt;</span></span>
521
+ Task: <span class="Tag"><span class="Tag">&lt;</span><span class="TagName">input</span> <span class="TagAttribute">type</span>=<span class="String"><span class="String">&quot;</span>text<span class="String">&quot;</span></span> <span class="TagAttribute">name</span>=<span class="String"><span class="String">&quot;</span>title<span class="String">&quot;</span></span> /<span class="Tag">&gt;</span></span><span class="Tag"><span class="Tag">&lt;</span><span class="TagName">br</span> /<span class="Tag">&gt;</span></span>
522
+ <span class="Tag"><span class="Tag">&lt;</span><span class="TagName">input</span> <span class="TagAttribute">type</span>=<span class="String"><span class="String">&quot;</span>submit<span class="String">&quot;</span></span> /<span class="Tag">&gt;</span></span>
523
+ <span class="Tag"><span class="Tag">&lt;/</span><span class="TagName">form</span><span class="Tag">&gt;</span></span>
524
+ <span class="Tag"><span class="Tag">&lt;/</span><span class="TagName">Page</span><span class="Tag">&gt;</span></span>
525
+ </code></pre>
526
+
527
+ <p>Alright, now just go and look at the result in the browser, try changing the things inside the Element and look at how it behaves.</p>
528
+
529
+ <h2 id="ninth_step_prettify">Ninth Step, Prettify</h2>
530
+
531
+ <p>We 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.</p>
532
+
533
+ <p>So, from what we have right now:</p>
534
+
535
+ <pre class="iplastic"><code class="ezamar" lang="ezamar"><span class="Tag"><span class="Tag">&lt;</span><span class="TagName">ul</span><span class="Tag">&gt;</span></span>
536
+ <span class="EmbeddedSource"><span class="EmbeddedSource">&lt;?r</span> <span class="EmbeddedSource"><span class="EmbeddedSource">@</span>tasks</span><span class="EmbeddedSource"><span class="EmbeddedSource">.</span><span class="FunctionName">each</span></span> <span class="Keyword">do </span><span class="EmbeddedSource">|</span><span class="EmbeddedSource">title</span><span class="EmbeddedSource">,</span> <span class="EmbeddedSource">status</span><span class="EmbeddedSource">,</span> <span class="EmbeddedSource">toggle</span><span class="EmbeddedSource">,</span> <span class="EmbeddedSource">delete</span><span class="EmbeddedSource">|</span> <span class="EmbeddedSource">?&gt;</span></span>
537
+ <span class="Tag"><span class="Tag">&lt;</span><span class="TagName">li</span><span class="Tag">&gt;</span></span>
538
+ #<span class="EmbeddedSource">{h title}</span>: #<span class="EmbeddedSource">{status}</span> [ #<span class="EmbeddedSource">{toggle}</span> | #<span class="EmbeddedSource">{delete}</span> ]
539
+ <span class="Tag"><span class="Tag">&lt;/</span><span class="TagName">li</span><span class="Tag">&gt;</span></span>
540
+ <span class="EmbeddedSource"><span class="EmbeddedSource">&lt;?r</span> <span class="Keyword">end</span> <span class="EmbeddedSource">?&gt;</span></span>
541
+ <span class="Tag"><span class="Tag">&lt;/</span><span class="TagName">ul</span><span class="Tag">&gt;</span></span>
542
+ </code></pre>
543
+
544
+ <p>To something like this:</p>
545
+
546
+ <pre class="iplastic"><code class="ezamar" lang="ezamar"><span class="Tag"><span class="Tag">&lt;</span><span class="TagName">table</span><span class="Tag">&gt;</span></span>
547
+ <span class="EmbeddedSource"><span class="EmbeddedSource">&lt;?r</span> <span class="EmbeddedSource"><span class="EmbeddedSource">@</span>tasks</span><span class="EmbeddedSource"><span class="EmbeddedSource">.</span><span class="FunctionName">each</span></span> <span class="Keyword">do </span><span class="EmbeddedSource">|</span><span class="EmbeddedSource">title</span><span class="EmbeddedSource">,</span> <span class="EmbeddedSource">status</span><span class="EmbeddedSource">,</span> <span class="EmbeddedSource">toggle</span><span class="EmbeddedSource">,</span> <span class="EmbeddedSource">delete</span><span class="EmbeddedSource">|</span> <span class="EmbeddedSource">?&gt;</span></span>
548
+ <span class="Tag"><span class="Tag">&lt;</span><span class="TagName">tr</span><span class="Tag">&gt;</span></span>
549
+ <span class="Tag"><span class="Tag">&lt;</span><span class="TagName">td</span> <span class="TagAttribute">class</span>=<span class="String"><span class="String">&quot;</span>title<span class="String">&quot;</span></span><span class="Tag">&gt;</span></span> #<span class="EmbeddedSource">{h title}</span> <span class="Tag"><span class="Tag">&lt;/</span><span class="TagName">td</span><span class="Tag">&gt;</span></span>
550
+ <span class="Tag"><span class="Tag">&lt;</span><span class="TagName">td</span> <span class="TagAttribute">class</span>=<span class="String"><span class="String">&quot;</span>status<span class="String">&quot;</span></span><span class="Tag">&gt;</span></span> #<span class="EmbeddedSource">{status}</span> <span class="Tag"><span class="Tag">&lt;/</span><span class="TagName">td</span><span class="Tag">&gt;</span></span>
551
+ <span class="Tag"><span class="Tag">&lt;</span><span class="TagName">td</span> <span class="TagAttribute">class</span>=<span class="String"><span class="String">&quot;</span>toggle<span class="String">&quot;</span></span><span class="Tag">&gt;</span></span> #<span class="EmbeddedSource">{toggle}</span> <span class="Tag"><span class="Tag">&lt;/</span><span class="TagName">td</span><span class="Tag">&gt;</span></span>
552
+ <span class="Tag"><span class="Tag">&lt;</span><span class="TagName">td</span> <span class="TagAttribute">class</span>=<span class="String"><span class="String">&quot;</span>delete<span class="String">&quot;</span></span><span class="Tag">&gt;</span></span> #<span class="EmbeddedSource">{delete}</span> <span class="Tag"><span class="Tag">&lt;/</span><span class="TagName">td</span><span class="Tag">&gt;</span></span>
553
+ <span class="Tag"><span class="Tag">&lt;/</span><span class="TagName">tr</span><span class="Tag">&gt;</span></span>
554
+ <span class="EmbeddedSource"><span class="EmbeddedSource">&lt;?r</span> <span class="Keyword">end</span> <span class="EmbeddedSource">?&gt;</span></span>
555
+ <span class="Tag"><span class="Tag">&lt;/</span><span class="TagName">table</span><span class="Tag">&gt;</span></span>
556
+ </code></pre>
557
+
558
+ <p>And, since we have proper classes to address some style sheets, jump into the Page element and add some style sheet:</p>
559
+
560
+ <pre class="iplastic"><code class="ezamar" lang="ezamar"><span class="Tag"><span class="Tag">&lt;</span><span class="TagName">head</span><span class="Tag">&gt;</span></span>
561
+ <span class="Tag"><span class="Tag">&lt;</span><span class="TagName">title</span><span class="Tag">&gt;</span></span>TodoList<span class="Tag"><span class="Tag">&lt;/</span><span class="TagName">title</span><span class="Tag">&gt;</span></span>
562
+ <span class="EmbeddedSource"> <span class="EmbeddedSource">&lt;</span><span class="TagName">style</span><span class="EmbeddedSource">&gt;</span></span>
563
+ <span class="EmbeddedSource"><span class="EmbeddedSource"> <span class="TagName">table</span> </span><span class="EmbeddedSource">{ width: 100%; }</span></span>
564
+ <span class="EmbeddedSource"><span class="EmbeddedSource"> <span class="TagName">tr</span> </span><span class="EmbeddedSource">{ background: #efe; width: 100%; }</span></span>
565
+ <span class="EmbeddedSource"><span class="EmbeddedSource"> <span class="TagName">tr</span><span class="TagAttribute"><span class="TagAttribute">:</span>hover</span> </span><span class="EmbeddedSource">{ background: #dfd; }</span></span>
566
+ <span class="EmbeddedSource"><span class="EmbeddedSource"> <span class="TagName">td</span><span class="TagAttribute"><span class="TagAttribute">.</span>title</span> </span><span class="EmbeddedSource">{ font-weight: bold; width: 60%; }</span></span>
567
+ <span class="EmbeddedSource"><span class="EmbeddedSource"> <span class="TagName">td</span><span class="TagAttribute"><span class="TagAttribute">.</span>status</span> </span><span class="EmbeddedSource">{ margin: 1em; }</span></span>
568
+ <span class="EmbeddedSource"><span class="EmbeddedSource"> <span class="TagName">a</span> </span><span class="EmbeddedSource">{ color: #3a3; }</span></span>
569
+ <span class="EmbeddedSource"> <span class="EmbeddedSource">&lt;/</span><span class="TagName">style</span><span class="EmbeddedSource">&gt;</span></span>
570
+ <span class="Tag"><span class="Tag">&lt;/</span><span class="TagName">head</span><span class="Tag">&gt;</span></span>
571
+ </code></pre>
572
+
573
+ <p>That looks quite a bit nicer, right? And yes, if you don&#8217;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.</p>
574
+
575
+ <p>I will leave this as an exercise to the reader.</p>
576
+
577
+ <h2 id="tenth_step_configuration">Tenth Step, Configuration</h2>
578
+
579
+ <p>To round up this tutorial a bit, let&#8217;s introduce you to configuration in Ramaze. This will not go into full depth of possibilities or a total coverage of the options, since they are bound to change over time.</p>
580
+
581
+ <p>First of all, the default port Ramaze runs on is 7000, but to make it a usual webserver it has to run on port 80. So, let&#8217;s add following line in your start.rb right after the lines of require you added before:</p>
582
+
583
+ <pre class="iplastic"><code class="ruby" lang="ruby"><span class="Support">Ramaze</span>::<span class="FunctionName">Global</span>.<span class="FunctionName">port</span> <span class="Keyword">=</span> <span class="Number">80</span>
584
+ </code></pre>
585
+
586
+ <p>Alright, that wasn&#8217;t that hard. Let&#8217;s say now you also want to run Mongrel instead of WEBrick, to get nice a bit of performance:</p>
587
+
588
+ <pre class="iplastic"><code class="ruby" lang="ruby"><span class="Support">Ramaze</span>::<span class="FunctionName">Global</span>.<span class="FunctionName">adapter</span> <span class="Keyword">=</span> <span class="Constant"><span class="Constant">:</span>mongrel</span>
589
+ </code></pre>
590
+
591
+ <p>To do this in a DRY way you could also do following:</p>
592
+
593
+ <pre class="iplastic"><code class="ruby" lang="ruby"><span class="Support">Ramaze</span>::<span class="FunctionName">Global</span>.<span class="FunctionName">setup</span> <span class="Keyword">do </span>|g|
594
+ g.<span class="FunctionName">port</span> <span class="Keyword">=</span> <span class="Number">80</span>
595
+ g.<span class="FunctionName">adapter</span> <span class="Keyword">=</span> <span class="Constant"><span class="Constant">:</span>mongrel</span>
596
+ <span class="Keyword">end</span>
597
+ </code></pre>
598
+
599
+ <p>It seems to be quite common to put this configuration into separate files so you can just require it on demand. There are other, slightly stronger way to set options, which is either using flags on the ramaze executable, or like this:</p>
600
+
601
+ <pre class="iplastic"><code class="ruby" lang="ruby"><span class="Support">Ramaze</span>.<span class="FunctionName">start</span> <span class="Constant"><span class="Constant">:</span>port</span> =&gt; <span class="Number">80</span>, <span class="Constant"><span class="Constant">:</span>adapter</span> =&gt; <span class="Constant"><span class="Constant">:</span>mongrel</span>
602
+ </code></pre>
603
+
604
+ <p>We haven&#8217;t started Ramaze directly as of yet, but this allows you to ignore the ramaze executable and just run your application by <code>ruby start.rb</code>.</p>
605
+
606
+ <h2 id="eleventh_step_refactor_with_aspecthelper">Eleventh Step, Refactor with AspectHelper</h2>
607
+
608
+ <p>Now, if you take a closer look at the Controller you will see:</p>
609
+
610
+ <pre class="iplastic"><code class="ruby" lang="ruby"><span class="Keyword">def</span> <span class="FunctionName">create</span>
611
+ title <span class="Keyword">=</span> request[<span class="String"><span class="String">'</span>title<span class="String">'</span></span>]
612
+ <span class="Support">TodoList</span>[title] <span class="Keyword">=</span> {<span class="Constant"><span class="Constant">:</span>done</span> =&gt; <span class="Identifier">false</span>}
613
+ redirect R(self)
614
+ <span class="Keyword">end</span>
615
+
616
+ <span class="Keyword">def</span> <span class="FunctionName">open</span> title
617
+ task_status title, <span class="Identifier">false</span>
618
+ redirect R(self)
619
+ <span class="Keyword">end</span>
620
+
621
+ <span class="Keyword">def</span> <span class="FunctionName">close</span> title
622
+ task_status title, <span class="Identifier">true</span>
623
+ redirect R(self)
624
+ <span class="Keyword">end</span>
625
+
626
+ <span class="Keyword">def</span> <span class="FunctionName">delete</span> title
627
+ <span class="Support">TodoList</span>.<span class="FunctionName">delete</span> title
628
+ redirect R(self)
629
+ <span class="Keyword">end</span>
630
+ </code></pre>
631
+
632
+ <p>We did some refactoring before, by introducing <code>#task_status</code>, but here we have repetition again: <code>redirect Rs()</code> <em>after</em> each method did its job.</p>
633
+
634
+ <p>However, we can take advantage of one of the helpers Ramaze offers, the AspectHelper. It allows you to easily wrap actions in your controller with other methods</p>
635
+
636
+ <p>In your Controller, replace the previous chunk with following:</p>
637
+
638
+ <pre class="iplastic"><code class="ruby" lang="ruby"><span class="Keyword">def</span> <span class="FunctionName">create</span>
639
+ title <span class="Keyword">=</span> request[<span class="String"><span class="String">'</span>title<span class="String">'</span></span>]
640
+ <span class="Support">TodoList</span>[title] <span class="Keyword">=</span> {<span class="Constant"><span class="Constant">:</span>done</span> =&gt; <span class="Identifier">false</span>}
641
+ <span class="Keyword">end</span>
642
+
643
+ <span class="Keyword">def</span> <span class="FunctionName">open</span> title
644
+ task_status title, <span class="Identifier">false</span>
645
+ <span class="Keyword">end</span>
646
+
647
+ <span class="Keyword">def</span> <span class="FunctionName">close</span> title
648
+ task_status title, <span class="Identifier">true</span>
649
+ <span class="Keyword">end</span>
650
+
651
+ <span class="Keyword">def</span> <span class="FunctionName">delete</span> title
652
+ <span class="Support">TodoList</span>.<span class="FunctionName">delete</span> title
653
+ <span class="Keyword">end</span>
654
+
655
+ helper <span class="Constant"><span class="Constant">:</span>aspect</span>
656
+ <span class="FunctionName">after</span>(<span class="Constant"><span class="Constant">:</span>create</span>, <span class="Constant"><span class="Constant">:</span>open</span>, <span class="Constant"><span class="Constant">:</span>close</span>, <span class="Constant"><span class="Constant">:</span>delete</span>){ <span class="FunctionName">redirect</span>(Rs()) }
657
+ </code></pre>
658
+
659
+ <p>Alright, that looks a lot nicer already and is definitely easier to maintain.</p>
660
+
661
+ <p>There is a symmetrical <code>before</code> aspect that you could take advantage of as well, and in case you want to add required authentication for all actions of a Controller you could use <code>before_all</code> and <code>after_all</code> instead of a list of action-names.</p>
662
+
663
+ <h2 id="twelfth_step_validation_and_errors">Twelfth Step, Validation and Errors</h2>
664
+
665
+ <p>Right now, all kinds of things could still go wrong when you do things like creating tasks with no title at all or try to open/close a task that does not exist. So in this step we will add some little checks for these cases.</p>
666
+
667
+ <p>First we head over to the Controller again and take a look at <code>#create</code>:</p>
668
+
669
+ <pre class="iplastic"><code class="ruby" lang="ruby"><span class="Keyword">def</span> <span class="FunctionName">create</span>
670
+ title <span class="Keyword">=</span> request[<span class="String"><span class="String">'</span>title<span class="String">'</span></span>]
671
+ <span class="Support">TodoList</span>[title] <span class="Keyword">=</span> {<span class="Constant"><span class="Constant">:</span>done</span> =&gt; <span class="Identifier">false</span>}
672
+ <span class="Keyword">end</span>
673
+ </code></pre>
674
+
675
+ <p>Here we just create a new task, no matter what we get. Every seasoned web-developer would advise you to be suspicious about all the input you receive from your users, so let&#8217;s apply this advice.</p>
676
+
677
+ <pre class="iplastic"><code class="ruby" lang="ruby"><span class="Keyword">def</span> <span class="FunctionName">create</span>
678
+ <span class="Keyword">if</span> title <span class="Keyword">=</span> request[<span class="String"><span class="String">'</span>title<span class="String">'</span></span>]
679
+ title.<span class="FunctionName">strip!</span>
680
+ <span class="Keyword">if</span> title.<span class="FunctionName">empty?</span>
681
+ <span class="FunctionName">failed</span>(<span class="String"><span class="String">&quot;</span>Please enter a title<span class="String">&quot;</span></span>)
682
+ redirect <span class="String"><span class="String">'</span>/new<span class="String">'</span></span>
683
+ <span class="Keyword">end</span>
684
+ <span class="Support">TodoList</span>[title] <span class="Keyword">=</span> {<span class="Constant"><span class="Constant">:</span>done</span> =&gt; <span class="Identifier">false</span>}
685
+ <span class="Keyword">end</span>
686
+ <span class="Keyword">end</span>
687
+ </code></pre>
688
+
689
+ <p>First of all we check if we got a request with a value for &#8216;title&#8217;, if we get none we just let the aspect kick in that will redirect the browser to the index. Next we strip the title of all spaces around it so we can check if it is empty. We will talk about the specifics of our error-handling now.</p>
690
+
691
+ <p>Ramaze has a helper called FlashHelper, that will keep a hash associated with the session for one request, afterwards the hash is thrown away. This is specifically useful for giving the user feedback while keeping a stateless approach.</p>
692
+
693
+ <p>Let me show you our <code>#failed</code> method (it goes in the private section to <code>#task_status</code>):</p>
694
+
695
+ <pre class="iplastic"><code class="ruby" lang="ruby"><span class="Keyword">def</span> <span class="FunctionName">failed</span>(<span class="Arguments">message</span>)
696
+ flash[<span class="Constant"><span class="Constant">:</span>error</span>] <span class="Keyword">=</span> message
697
+ <span class="Keyword">end</span>
698
+ </code></pre>
699
+
700
+ <p>Duh, you may say, wouldn&#8217;t that fit in the one line instead of the call to <code>#failed</code>? Indeed, it would, but let me remind you, we have no checks for changing the status of a task yet. We will need error-handling there as well, so we just keep our code DRY and maintainable by collecting shared behaviour in small pieces.</p>
701
+
702
+ <p>Now on to the <code>#task_status</code>:</p>
703
+
704
+ <pre class="iplastic"><code class="ruby" lang="ruby"><span class="Keyword">def</span> <span class="FunctionName">task_status</span> title, status
705
+ <span class="Keyword">unless</span> task <span class="Keyword">=</span> <span class="Support">TodoList</span>[title]
706
+ failed <span class="String"><span class="String">&quot;</span>No such Task: `<span class="String"><span class="String">#{</span>title<span class="String">}</span></span>'<span class="String">&quot;</span></span>
707
+ redirect_referer
708
+ <span class="Keyword">end</span>
709
+
710
+ task[<span class="Constant"><span class="Constant">:</span>done</span>] <span class="Keyword">=</span> status
711
+ <span class="Support">TodoList</span>[title] <span class="Keyword">=</span> task
712
+ <span class="Keyword">end</span>
713
+ </code></pre>
714
+
715
+ <p>That used to look like this:</p>
716
+
717
+ <pre class="iplastic"><code class="ruby" lang="ruby"><span class="Keyword">def</span> <span class="FunctionName">task_status</span> title, status
718
+ task <span class="Keyword">=</span> <span class="Support">TodoList</span>[title]
719
+ task[<span class="Constant"><span class="Constant">:</span>done</span>] <span class="Keyword">=</span> status
720
+ <span class="Support">TodoList</span>[title] <span class="Keyword">=</span> task
721
+ <span class="Keyword">end</span>
722
+ </code></pre>
723
+
724
+ <p>So in fact all we added is a check whether a task already exists, set an error-message in case it doesn&#8217;t and redirect to wherever the browser came from.</p>
725
+
726
+ <p>But what about actually showing the error-messages we so carefully set? Well, where do we change the view? Right, in the templates. But both templates we have so far (index and new) share this behaviour, so we head over to the Element and add in the right place:</p>
727
+
728
+ <pre class="iplastic"><code class="ezamar" lang="ezamar"><span class="Tag"><span class="Tag">&lt;</span><span class="TagName">body</span><span class="Tag">&gt;</span></span>
729
+ <span class="Tag"><span class="Tag">&lt;</span><span class="TagName">h1</span><span class="Tag">&gt;</span></span>#<span class="EmbeddedSource">{@title}</span><span class="Tag"><span class="Tag">&lt;/</span><span class="TagName">h1</span><span class="Tag">&gt;</span></span>
730
+ <span class="EmbeddedSource"><span class="EmbeddedSource">&lt;?r</span> <span class="Keyword">if</span> flash<span class="EmbeddedSource">[</span><span class="Constant"><span class="Constant">:</span>error</span><span class="EmbeddedSource">]</span> <span class="EmbeddedSource">?&gt;</span></span>
731
+ <span class="Tag"><span class="Tag">&lt;</span><span class="TagName">div</span> <span class="TagAttribute">class</span>=<span class="String"><span class="String">&quot;</span>error<span class="String">&quot;</span></span><span class="Tag">&gt;</span></span>
732
+ \\#<span class="EmbeddedSource">{flash[:error]}</span>
733
+ <span class="Tag"><span class="Tag">&lt;/</span><span class="TagName">div</span><span class="Tag">&gt;</span></span>
734
+ <span class="EmbeddedSource"><span class="EmbeddedSource">&lt;?r</span> <span class="Keyword">end</span> <span class="EmbeddedSource">?&gt;</span></span>
735
+ #<span class="EmbeddedSource">{content}</span>
736
+ <span class="Tag"><span class="Tag">&lt;/</span><span class="TagName">body</span><span class="Tag">&gt;</span></span>
737
+ </code></pre>
738
+
739
+ <p>The only thing special about it is the <code>\\#{flash[:error]}</code>, we have to escape the <code>#</code> so it won&#8217;t evaluate this immediately but wait until it is really rendered. As a note, If you read this as pure markaby, the double backslash is to output properly to HTML, just use one instead. Again, you can add some nifty style for that.</p>
740
+
741
+ <p>To be continued&#8230;</p>
742
+ </body></html>