ramaze 2011.07.25 → 2011.10.23

Sign up to get free protection for your applications and to get access to all the features.
Files changed (181) hide show
  1. data/.gitignore +3 -0
  2. data/.mailmap +3 -2
  3. data/.travis.yml +17 -0
  4. data/.yardopts +13 -0
  5. data/README.md +95 -352
  6. data/examples/app/blog/app.rb +25 -64
  7. data/examples/app/blog/config.ru +11 -9
  8. data/examples/app/blog/controller/init.rb +29 -86
  9. data/examples/app/blog/controller/posts.rb +232 -0
  10. data/examples/app/blog/controller/users.rb +160 -0
  11. data/examples/app/blog/layout/default.xhtml +61 -0
  12. data/examples/app/blog/migrations/01_create_schema.rb +50 -0
  13. data/examples/app/blog/model/comment.rb +41 -54
  14. data/examples/app/blog/model/init.rb +41 -13
  15. data/examples/app/blog/model/post.rb +35 -0
  16. data/examples/app/blog/model/user.rb +105 -0
  17. data/examples/app/blog/public/.htaccess +24 -0
  18. data/examples/app/blog/public/css/grid.css +107 -0
  19. data/examples/app/blog/public/css/layout.css +203 -0
  20. data/examples/app/blog/public/css/reset.css +123 -0
  21. data/examples/app/blog/public/css/text.css +109 -0
  22. data/examples/app/blog/public/dispatch.fcgi +11 -0
  23. data/examples/app/blog/public/favicon.ico +0 -0
  24. data/examples/app/blog/public/images/bg.png +0 -0
  25. data/examples/app/blog/start.rb +18 -3
  26. data/examples/app/blog/view/feed.xhtml +23 -0
  27. data/examples/app/blog/view/form.xhtml +11 -0
  28. data/examples/app/blog/view/index.xhtml +44 -0
  29. data/examples/app/blog/view/users/form.xhtml +12 -0
  30. data/examples/app/blog/view/users/index.xhtml +30 -0
  31. data/examples/app/blog/view/users/login.xhtml +8 -0
  32. data/examples/app/blog/view/view.xhtml +68 -0
  33. data/{doc → guide}/AUTHORS +5 -3
  34. data/{doc → guide}/CHANGELOG +428 -0
  35. data/{doc/GPL → guide/GPL_LICENSE} +0 -0
  36. data/{doc/COPYING → guide/RUBY_LICENSE} +3 -6
  37. data/guide/_static/logo.png +0 -0
  38. data/guide/_static/logo.svg +49 -0
  39. data/guide/_static/ramaze_console.png +0 -0
  40. data/guide/css/common.css +20 -0
  41. data/guide/general/cache.md +167 -0
  42. data/guide/general/configuration.md +168 -0
  43. data/guide/general/contributing.md +108 -0
  44. data/guide/general/controllers.md +115 -0
  45. data/guide/general/helpers.md +76 -0
  46. data/guide/general/installation.md +58 -0
  47. data/guide/general/logging.md +99 -0
  48. data/guide/general/middlewares.md +100 -0
  49. data/guide/general/models.md +78 -0
  50. data/guide/general/principles.md +53 -0
  51. data/guide/general/ramaze_command.md +155 -0
  52. data/guide/general/routes.md +81 -0
  53. data/guide/general/sessions.md +140 -0
  54. data/guide/general/special_thanks.md +67 -0
  55. data/guide/general/testing.md +61 -0
  56. data/guide/general/views.md +322 -0
  57. data/guide/tutorials/introduction.md +259 -0
  58. data/lib/proto/config.ru +1 -1
  59. data/lib/proto/public/favicon.ico +0 -0
  60. data/lib/proto/view/index.xhtml +7 -7
  61. data/lib/ramaze.rb +4 -4
  62. data/lib/ramaze/app.rb +11 -11
  63. data/lib/ramaze/app_graph.rb +2 -4
  64. data/lib/ramaze/bin/console.rb +3 -3
  65. data/lib/ramaze/bin/create.rb +2 -2
  66. data/lib/ramaze/bin/restart.rb +4 -4
  67. data/lib/ramaze/bin/runner.rb +5 -5
  68. data/lib/ramaze/bin/start.rb +19 -4
  69. data/lib/ramaze/bin/status.rb +3 -3
  70. data/lib/ramaze/bin/stop.rb +3 -3
  71. data/lib/ramaze/cache.rb +1 -0
  72. data/lib/ramaze/cache/lru.rb +8 -4
  73. data/lib/ramaze/cache/memcache.rb +32 -13
  74. data/lib/ramaze/cache/redis.rb +164 -0
  75. data/lib/ramaze/cache/sequel.rb +43 -28
  76. data/lib/ramaze/controller.rb +1 -2
  77. data/lib/ramaze/dependencies.rb +40 -3
  78. data/lib/ramaze/helper/bench.rb +26 -16
  79. data/lib/ramaze/helper/blue_form.rb +46 -73
  80. data/lib/ramaze/helper/cache.rb +10 -6
  81. data/lib/ramaze/helper/csrf.rb +35 -39
  82. data/lib/ramaze/helper/disqus.rb +5 -4
  83. data/lib/ramaze/helper/email.rb +35 -24
  84. data/lib/ramaze/helper/erector.rb +9 -13
  85. data/lib/ramaze/helper/flash.rb +7 -9
  86. data/lib/ramaze/helper/formatting.rb +194 -179
  87. data/lib/ramaze/helper/gravatar.rb +4 -8
  88. data/lib/ramaze/helper/identity.rb +3 -3
  89. data/lib/ramaze/helper/layout.rb +23 -8
  90. data/lib/ramaze/helper/markaby.rb +1 -1
  91. data/lib/ramaze/helper/paginate.rb +46 -39
  92. data/lib/ramaze/helper/request_accessor.rb +3 -1
  93. data/lib/ramaze/helper/simple_captcha.rb +18 -17
  94. data/lib/ramaze/helper/stack.rb +1 -1
  95. data/lib/ramaze/helper/tagz.rb +4 -2
  96. data/lib/ramaze/helper/upload.rb +523 -0
  97. data/lib/ramaze/helper/user.rb +4 -8
  98. data/lib/ramaze/helper/xhtml.rb +11 -15
  99. data/lib/ramaze/log.rb +9 -6
  100. data/lib/ramaze/log/rotatinginformer.rb +62 -27
  101. data/lib/ramaze/log/syslog.rb +20 -15
  102. data/lib/ramaze/log/xosd.rb +2 -1
  103. data/lib/ramaze/reloader.rb +2 -0
  104. data/lib/ramaze/request.rb +11 -10
  105. data/lib/ramaze/setup.rb +23 -6
  106. data/lib/ramaze/snippets/array/put_within.rb +3 -9
  107. data/lib/ramaze/snippets/binding/locals.rb +5 -10
  108. data/lib/ramaze/snippets/fiber.rb +1 -23
  109. data/lib/ramaze/snippets/kernel/pretty_inspect.rb +3 -6
  110. data/lib/ramaze/snippets/numeric/filesize_format.rb +3 -5
  111. data/lib/ramaze/snippets/numeric/time.rb +3 -7
  112. data/lib/ramaze/snippets/object/__dir__.rb +3 -7
  113. data/lib/ramaze/snippets/object/instance_variable_defined.rb +3 -6
  114. data/lib/ramaze/snippets/object/pretty.rb +3 -7
  115. data/lib/ramaze/snippets/object/scope.rb +7 -9
  116. data/lib/ramaze/snippets/proc/locals.rb +12 -12
  117. data/lib/ramaze/snippets/ramaze/acquire.rb +15 -14
  118. data/lib/ramaze/snippets/ramaze/deprecated.rb +1 -1
  119. data/lib/ramaze/snippets/ramaze/fiber.rb +1 -1
  120. data/lib/ramaze/snippets/ramaze/lru_hash.rb +2 -3
  121. data/lib/ramaze/snippets/ramaze/struct.rb +2 -4
  122. data/lib/ramaze/snippets/string/camel_case.rb +8 -10
  123. data/lib/ramaze/snippets/string/color.rb +3 -4
  124. data/lib/ramaze/snippets/string/end_with.rb +3 -6
  125. data/lib/ramaze/snippets/string/esc.rb +3 -8
  126. data/lib/ramaze/snippets/string/ord.rb +3 -8
  127. data/lib/ramaze/snippets/string/snake_case.rb +6 -9
  128. data/lib/ramaze/snippets/string/start_with.rb +3 -8
  129. data/lib/ramaze/snippets/string/unindent.rb +3 -6
  130. data/lib/ramaze/snippets/thread/into.rb +1 -3
  131. data/lib/ramaze/spec.rb +2 -31
  132. data/lib/ramaze/spec/bacon.rb +18 -2
  133. data/lib/ramaze/version.rb +1 -1
  134. data/lib/ramaze/view.rb +1 -1
  135. data/ramaze.gemspec +1 -1
  136. data/spec/helper.rb +2 -1
  137. data/spec/ramaze/bin/start.rb +16 -20
  138. data/spec/ramaze/cache/localmemcache.rb +4 -7
  139. data/spec/ramaze/cache/memcache.rb +3 -1
  140. data/spec/ramaze/cache/redis.rb +62 -0
  141. data/spec/ramaze/helper/blue_form.rb +33 -4
  142. data/spec/ramaze/helper/layout.rb +40 -7
  143. data/spec/ramaze/helper/upload.rb +149 -0
  144. data/spec/ramaze/helper/uploads/text_1.txt +1 -0
  145. data/spec/ramaze/helper/uploads/text_2.txt +1 -0
  146. data/spec/ramaze/log/growl.rb +4 -6
  147. data/spec/ramaze/log/syslog.rb +6 -0
  148. data/spec/ramaze/view/lokar.rb +5 -0
  149. data/spec/ramaze/view/nagoro.rb +5 -0
  150. data/tasks/authors.rake +1 -1
  151. data/tasks/bacon.rake +14 -5
  152. data/tasks/changelog.rake +1 -1
  153. data/tasks/yard.rake +12 -4
  154. metadata +277 -239
  155. data/doc/LEGAL +0 -26
  156. data/examples/app/blog/README +0 -3
  157. data/examples/app/blog/controller/comment.rb +0 -45
  158. data/examples/app/blog/controller/entry.rb +0 -85
  159. data/examples/app/blog/controller/main.rb +0 -20
  160. data/examples/app/blog/controller/tag.rb +0 -9
  161. data/examples/app/blog/layout/default.nag +0 -31
  162. data/examples/app/blog/model/entry.rb +0 -89
  163. data/examples/app/blog/model/tag.rb +0 -36
  164. data/examples/app/blog/public/css/screen.css +0 -273
  165. data/examples/app/blog/spec/blog.rb +0 -87
  166. data/examples/app/blog/view/comment/form.nag +0 -10
  167. data/examples/app/blog/view/comment/show.nag +0 -16
  168. data/examples/app/blog/view/entry/edit.nag +0 -14
  169. data/examples/app/blog/view/entry/feed.atom.nag +0 -8
  170. data/examples/app/blog/view/entry/feed.rss.nag +0 -7
  171. data/examples/app/blog/view/entry/index.nag +0 -7
  172. data/examples/app/blog/view/entry/new.nag +0 -13
  173. data/examples/app/blog/view/entry/show.nag +0 -36
  174. data/examples/app/blog/view/feed.atom.nag +0 -18
  175. data/examples/app/blog/view/feed.rss.nag +0 -25
  176. data/examples/app/blog/view/index.nag +0 -6
  177. data/examples/app/blog/view/tag/index.nag +0 -5
  178. data/lib/proto/public/ramaze.png +0 -0
  179. data/lib/ramaze/rest.rb +0 -36
  180. data/spec/ramaze/rest.rb +0 -28
  181. data/tasks/rcov.rake +0 -22
@@ -0,0 +1,78 @@
1
+ # Models
2
+
3
+ Unlike other frameworks Ramaze does not ship with a database toolkit. One of the
4
+ ideas of Ramaze is that it allows you to choose your own set of tools, you're
5
+ not forced to use what we think is best. Ramaze allows you to use
6
+ [ActiveRecord][ar], [Sequel][sequel] or anything else. For the simplicity of
7
+ this user guide we'll use Sequel. In short, Sequel is a database toolkit that
8
+ allows you to write SQL statements using Ruby methods as well as providing an
9
+ ORM (Object Relationship Mapper).
10
+
11
+ Let's say we're creating a simple blog application. Each blog has posts,
12
+ comments, users and perhaps some categories. We're not going to create a model
13
+ for each of these entities in this guide but instead we'll focus on the Post
14
+ model. The most basic form of a model looks like the following:
15
+
16
+ class Post < Sequel::Model
17
+
18
+ end
19
+
20
+ From this point on we can load our model (given we have established a database
21
+ connection) and call methods from it. For example, if we want to retrieve the
22
+ post with ID #1 we'd do the following:
23
+
24
+ Post[1] # => SELECT * FROM posts WHERE id = 1
25
+
26
+ Performing a WHERE clause and retrieving a single record can be done by passing
27
+ a hash to the [] method:
28
+
29
+ Post[:title => 'Ramaze is Great'] # => SELECT * FROM posts WHERE title = 'Ramaze is Great'
30
+
31
+ ## Controllers And Models
32
+
33
+ Of course using a model on its own isn't really going to work. Let's combine
34
+ our Post model mentioned earlier with a controller called "Posts".
35
+
36
+ require 'ramaze'
37
+ require 'model/post'
38
+
39
+ class Posts < Ramaze::Controller
40
+ map '/'
41
+
42
+ def index
43
+ @posts = Post.all
44
+ end
45
+
46
+ def edit(id)
47
+ # Arguments are passed as strings so it's a good idea to convert them
48
+ @post = Post[id.to_i]
49
+ end
50
+ end
51
+
52
+ This is a somewhat more advanced example of how to use controllers and models.
53
+ However, it's nothing ground breaking and shouldn't be too hard to understand.
54
+ In the index() method we're simply retrieving all posts by calling Post#all and
55
+ storing them in an instance variable. In the edit() method we're retrieving the
56
+ post based on the given ID.
57
+
58
+ In the edit() method the "id" variable is also converted to an integer. The
59
+ reason for this is that Ramaze doesn't know what types the URI segments should
60
+ be and thus passes them as a string to the called method. While Sequel itself
61
+ won't have any trouble handling this it's a good practice to send the correct
62
+ types as other database toolkits might trigger errors when they receive a string
63
+ value while expecting an integer.
64
+
65
+ ## Supported Toolkits
66
+
67
+ * [ActiveRecord][ar]
68
+ * [M4DBI][m4dbi]
69
+ * [Sequel][sequel]
70
+ * [DataMapper][datamapper]
71
+
72
+ Besides these listed toolkits Ramaze should work with any other toolkit, these
73
+ however are the ones that have been confirmed to work just fine with Ramaze.
74
+
75
+ [sequel]: http://sequel.rubyforge.org/
76
+ [ar]: http://ar.rubyonrails.org/
77
+ [m4dbi]: https://github.com/Pistos/m4dbi
78
+ [datamapper]: http://datamapper.org/
@@ -0,0 +1,53 @@
1
+ # Principles
2
+
3
+ There are some basic principles that Ramaze tries to follow:
4
+
5
+ * KISS (Keep It Super Simple)
6
+
7
+ Ramaze doesn't introduce any major change of paradigm for everyone familiar
8
+ with Ruby and the basics of Web-development.
9
+
10
+ * POLS (Principle Of Least Surprise)
11
+
12
+ Ramaze tries to be intuitive and easy to learn. Most functionality is built in
13
+ a way to help, not to obfuscate or confuse.
14
+
15
+ * Modular design
16
+
17
+ Use what you want and how you want it.Through Ruby Ramaze provides one of the
18
+ most powerful programming-languages available, giving you full control over
19
+ your system.
20
+
21
+ Even the most essential parts of Ramaze can easily be replaced and/or modified
22
+ without losing the advantage of the whole framework.
23
+
24
+ * Minimal dependencies
25
+
26
+ Nothing besides Ruby is required for the basic features.
27
+ Of course you can take advantage of several wonderful libraries, but Ramaze is
28
+ built in a way to be run on any basic setup.
29
+
30
+ * Documentation
31
+
32
+ Document everything, classes, modules, methods, configuration
33
+ and so on. Through 100% documentation Ramaze gives the developer easy and
34
+ solid understanding of the underlying concepts and functionality.
35
+
36
+ * Open development
37
+
38
+ Everyone is welcome to contribute to Ramaze in the easiest
39
+ way possible. The repository is open for patches passing the Test-suite.
40
+
41
+ * Examples
42
+
43
+ Everyone learns different, some only read the source, others browse
44
+ documentation, but everyone loves examples for a quick and painless start.
45
+ Ramaze addresses this need and offers a wide variety of examples of usage,
46
+ basic functionality, project-layout and more advanced applications.
47
+
48
+ * Fully BDD (Behaviour Driven Design)
49
+
50
+ Ramaze has a very complete set of so-called specifications built by RSpec.
51
+ These specs define the way Ramaze has to behave. The specs are checked every
52
+ time a new patch is pushed into the repository, deciding whether the changes
53
+ the patch applies are valid and don't break the framework.
@@ -0,0 +1,155 @@
1
+ ## Ramaze Command
2
+
3
+ Ramaze ships with a relatively simple command, named "ramaze". This command can
4
+ be used to create new applications as well as starting them. To make reading
5
+ this guide easier we'll call this command "bin/ramaze" from now on.
6
+
7
+ <div class="note deprecated">
8
+ <p>
9
+ <strong>Warning</strong>: bin/ramaze is not a scaffolding application.
10
+ It can merely be used for some basic application management and creating
11
+ a basic Ramaze application.
12
+ </p>
13
+ </div>
14
+
15
+ ## Creating Applications
16
+
17
+ As mentioned earlier bin/ramaze can be used to create new applications. In order
18
+ to create a new application in the current directory all you have to do is
19
+ executing the following command:
20
+
21
+ $ ramaze create APPNAME
22
+
23
+ APPNAME is the name of your new application and will also be used as the
24
+ directory name. If the application was named "blog" there would now be a
25
+ directory called "blog" in the current one. This directory will contain all
26
+ basic files that can be used for a Ramaze powered application.
27
+
28
+ Each new application has the following structure:
29
+
30
+ .__ app.rb
31
+ |__ config.ru
32
+ |__ controller
33
+ |   |__ init.rb
34
+ |   |__ main.rb
35
+ |
36
+ |__ layout
37
+ |   |__ default.xhtml
38
+ |
39
+ |__ model
40
+ |   |__ init.rb
41
+ |
42
+ |__ public
43
+ | |
44
+ |   |__ css
45
+ |   |   |__ screen.css
46
+ | |
47
+ |   |__ dispatch.fcgi
48
+ |   |__ favicon.ico
49
+ |   |__ js
50
+ |   |   |__ jquery.js
51
+ | |
52
+ |   |__ ramaze.png
53
+ |
54
+ |__ spec
55
+ |   |__ main.rb
56
+ |
57
+ |__ start.rb
58
+ |__ view
59
+ |__ index.xhtml
60
+
61
+ ## Application Prototypes
62
+
63
+ Due to Ramaze's nature it's very easy to create your own application prototype
64
+ if you dislike the default one. For example, I've made some small modifications
65
+ to the default prototype so that it looks like the followng:
66
+
67
+ .__ app.rb
68
+ |__ config
69
+ |   |__ config.rb
70
+ |   |__ database.rb
71
+ |   |__ middlewares.rb
72
+ |   |__ requires.rb
73
+ |
74
+ |__ config.ru
75
+ |__ controller
76
+ |__ layout
77
+ |   |__ default.xhtml
78
+ |
79
+ |__ log
80
+ |__ public
81
+ |__ spec
82
+ |__ start.rb
83
+ |__ view
84
+
85
+ This prototype is basically a minimal version of the default one but with a
86
+ special directory for all configuration files. In order to use this prototype I
87
+ had to make some small changes to app.rb, the look like the following:
88
+
89
+ require 'ramaze'
90
+
91
+ # Load the file that in turn will load all gems, keeps this file clean
92
+ require __DIR__('config/requires')
93
+
94
+ # Configure our application
95
+ require __DIR__('config/config')
96
+
97
+ # Load our database settings
98
+ require __DIR__('config/database')
99
+
100
+ # Load all Rack middlewares
101
+ require __DIR__('config/middlewares')
102
+
103
+ # Load all controllers
104
+ Dir.glob(__DIR__('controller') + '/**/*.rb').each do |f|
105
+ require f
106
+ end
107
+
108
+ This is only a basic example of the flexibility of Ramaze, I highly recommend
109
+ you playing around with your own prototypes as it's a great way to learn the
110
+ basics of Ramaze and to really understand how flexible Ramaze is.
111
+
112
+
113
+ <div class="note todo">
114
+ <p>
115
+ <strong>Note</strong>: This prototype does not come with Ramaze, it's
116
+ just an example of what you could make yourself.
117
+ </p>
118
+ </div>
119
+
120
+ ## Running Applications
121
+
122
+ When you've created an application there are three ways of running it. You can
123
+ either use your server's command such as `thin` or `unicorn` but you can also
124
+ use bin/ramaze. When starting your application with bin/ramaze it will use the
125
+ appropriate server according to the settings set in "config.ru" or "star.rb".
126
+ An example of using this command is as simple as the following:
127
+
128
+ $ ramaze start
129
+
130
+ On top of these two ways you can also start your Ramaze application by calling
131
+ the "start.rb" file using the ruby binary:
132
+
133
+ $ ruby start.rb
134
+
135
+ If you want to stop the running application you can simply close it by using the
136
+ key combination Ctrl+C.
137
+
138
+ <div class="note todo">
139
+ <p>
140
+ <strong>Note</strong>: There are many different ways to start your
141
+ application depending on the server you're using. Fore more information
142
+ it's best to look at the documentation of your favorite webserver.
143
+ </p>
144
+ </div>
145
+
146
+ ## Ramaze Console
147
+
148
+ The bin/ramaze command allows you to run an interactive Ramaze session just
149
+ like IRB. In fact, Ramaze actually uses IRB. To invoke the Ramaze console simple
150
+ execute `ramaze console` and you're good to go. This console gives you full
151
+ access to your application and thus can be very useful for debugging purposes.
152
+
153
+ An example of a Ramaze console session can be seen in the image below.
154
+
155
+ ![Ramaze Console](_static/ramaze_console.png)
@@ -0,0 +1,81 @@
1
+ # Routes
2
+
3
+ While in many cases the default route system that comes with Ramaze is good
4
+ enough there will be times when you want pretty URLs (or just different ones).
5
+ Ramaze allows you to do all this using the class Ramaze::Route (it's an alias
6
+ of Innate::Route). This class allows you to create routes using simple strings,
7
+ regular expressions and lambdas. Let's say we have the following URLs:
8
+
9
+ * /users/index
10
+ * /users/profile/yorickpeterse
11
+ * /users/edit/yorickpeterse
12
+
13
+ Our goal is to rewrite these URLs to the following:
14
+
15
+ * /users/list
16
+ * /users/yorickpeterse
17
+ * /users/yorickpeterse/edit
18
+
19
+ In order to fully explain the routing system will use the three available
20
+ possibilities: strings, regular expressions and lambdas.
21
+
22
+ ## String Routes
23
+
24
+ Routes that use a string are the most basic form of routing. You simply specify
25
+ a request URI and the action to call instead of the normal one:
26
+
27
+ Ramaze::Route['/foobar'] = '/baz/bar'
28
+
29
+ This route tells Ramaze that every request to /foobar should be sent to /baz/bar
30
+ instead. While string based routes are the easiest to use they're also the most
31
+ limited one, they can merely be used to redirect A to B. If we look at our list
32
+ of URLs the only one we can rewrite using this form of routing is the first one:
33
+
34
+ Ramaze::Route['/users/list'] = '/users/index'
35
+
36
+ This forwards all requests that were sent to /users/list to /users/index.
37
+
38
+ ## Regular Expression Routes
39
+
40
+ Using regular expressions in routes makes it possible to have more dynamic
41
+ routes. Routes that use regular expressions look like the following:
42
+
43
+ Ramaze::Route[/user-([0-9]+)/] = '/users/%d'
44
+
45
+ This route forwards requests such as /user-10 and /user-1234 to /users/10 and
46
+ /users/1234. As you can see there's a "%d" in the value which is replaced with
47
+ the value of the group ([0-9]+). When using regular expressions for your routes
48
+ you can use sprintf characters in the value (%s, %d, etc).
49
+
50
+ So what about our list of URLs? Let's rewrite the second URL:
51
+
52
+ Ramaze::Route['/users/([\w]+)'] = '/users/profile/%s'
53
+
54
+ And there we go, all calls to /users/NAME (where NAME is the name of a user)
55
+ will be routed to /users/profile/NAME.
56
+
57
+ ## Lambda Routes
58
+
59
+ The last method of routing calls can be done using lambdas. The key of the []=
60
+ method will be the name of a route (can be anything really) and the value a
61
+ lambda that takes two parameters, the request path and a variable containing the
62
+ request data:
63
+
64
+ Ramaze::Route['my funky lambda route'] = lambda do |path, request|
65
+
66
+ end
67
+
68
+ In this lambda you're free to do whatever you want as long as you either return
69
+ a new path or nil (anything else will result in an error). Say we wanted to
70
+ route our last URL we'd do it as following:
71
+
72
+ Ramaze::Route['edit users'] = lambda do |path, request|
73
+ if path =~ /users\/edit\/([\w]+)/
74
+ return "/users/#{$1}/edit"
75
+ end
76
+ end
77
+
78
+ This route redirects everything from /users/NAME/edit to /users/edit/NAME.
79
+ Everything else is unaffected by this route since it only returns a value when
80
+ the path matches the given regular expression. Note that lambdas can actually
81
+ contain a "return" statement so the code above is perfectly valid.
@@ -0,0 +1,140 @@
1
+ # Sessions
2
+
3
+ The term sessions is used for data associated to a specific client. The easiest
4
+ example of a session is a simple cookie containing some very basic data such as
5
+ a user's name.
6
+
7
+ ## Initializing Sessions
8
+
9
+ Ramaze lazy-loads the session system that it's ship with. This means that if you
10
+ never use any session related data a session will not be created. As soon as you
11
+ call the main object for working with sessions (simply called "session") or add
12
+ data to the flash (more on that later) Ramaze will load the session adapter
13
+ automatically. This prevents you from having to manually write code that invokes
14
+ a session for all your projects.
15
+
16
+ So how do we actually start a session? As mentioned earlier this can be done in
17
+ two different ways, calling session or flash. If you want to store data in the
18
+ session until the client's session is destroyed (or the data is removed) it's
19
+ best to use session, if you only want to store something until the client is
20
+ redirected to another page (or just visits a page himself) you should use flash.
21
+
22
+ ## The Session Object
23
+
24
+ As mentioned earlier session is used for data that should be stored until the
25
+ client's session is destroyed or the data is removed. A good example of this
26
+ sort of data is a boolean that indicates if the user is logged in or not, you
27
+ don't want the user to re-authenticate over and over again thus you store the
28
+ data using the session object. Storing data using this method is incredible
29
+ simple and works a bit like you're storing data in a hash:
30
+
31
+ session[:logged_in] = true
32
+
33
+ In the above example we stored a boolean with a value of "true" in the current
34
+ client's session under the name ":logged_in". If we want to retrieve this data
35
+ somewhere else in the application all we'd have to do is the following:
36
+
37
+ session[:logged_in] # => true
38
+
39
+ A better example would be a simple counter that tracks the amount of times a
40
+ user has visited your application:
41
+
42
+ class Counter < Ramaze::Controller
43
+ map '/'
44
+
45
+ def index
46
+ # If no data was found for the given key session returns nil
47
+ if !session[:visits].nil?
48
+ session[:visits] = 0
49
+ else
50
+ session[:visits] += 1
51
+ end
52
+
53
+ "You have visitied this page #{session[:visits]} times."
54
+ end
55
+ end
56
+
57
+ In this relatively basic controller a user's amount of visits to the index()
58
+ method will be stored in the session and displayed afterwards. Now it's time
59
+ for the true magic. The session object is an instance of Innate::Session and
60
+ has a few extra methods besides [] and []=. These methods are delete(), clear(),
61
+ flush(), resid!() and sid(). We're not going to cover all methods but we will
62
+ look at the delete() and resid() methods.
63
+
64
+ ## Session.delete
65
+
66
+ The method Session.delete can be used to remove a chunk of data from the
67
+ client's session. In order to delete our amount of visits all we'd have to do
68
+ is the following:
69
+
70
+ session.delete(:visits)
71
+
72
+ From this point on the "visits" key is set to nil until the user visits the
73
+ index page again.
74
+
75
+ ## Session.resid!
76
+
77
+ Session.resid! can be used to regenerate the client's session ID without
78
+ destroying the session data. This method is extremely useful for authentication
79
+ systems as it can be used to prevent session fixation attacks by generating a
80
+ new session ID every N minutes or whenever a certain action is triggered (e.g.
81
+ the user logs in). Using this method is very simple and only requires the
82
+ following to be done:
83
+
84
+ session.resid!
85
+
86
+ ## The Flash
87
+
88
+ First of all, this has nothing to do with Adobe's Flash or
89
+ [The Flash][the flash]. Flashdata is a form of session data that is removed as
90
+ soon as the client requests a new resource. This means that if something is
91
+ stored in the flash and the user is redirected the data will be automatically
92
+ removed. One of the things the flash data can be used for is storing
93
+ notifications that are displayed if a blog post has been saved successfully.
94
+ Storing data in the flash works similar to storing data in the session and can
95
+ be done by calling the flash object:
96
+
97
+ flash[:message] = "Hello, Ramaze!"
98
+
99
+ If we want to remove something from the flash we can call Flash.delete similar
100
+ to Session.delete:
101
+
102
+ flash.delete(:message)
103
+
104
+ Note that due to the nature of the flash data you'd have to do this before the
105
+ client requests a new resource as the data will be deleted automatically at
106
+ that point.
107
+
108
+ To integrate flash with your application views include {Ramaze::Helper::Flash}
109
+ in your controller and call function ``flashbox`` inside the view.
110
+
111
+ To change the markup of the flashbox generated HTML, use the following trait
112
+ inside your controller:
113
+
114
+ trait :flashbox => "<div class=\"alert-message %key\"><p>%value</p></div>"
115
+
116
+ Below is an example of how the flash data can be used in a typical Ramaze
117
+ application:
118
+
119
+ class Blogs < Ramaze::Controller
120
+ map '/'
121
+ helper :flash
122
+
123
+ def index
124
+ flash[:message]
125
+ end
126
+
127
+ def set_message
128
+ flash[:message] = "Hello, Ramaze!"
129
+ redirect(Blogs.r(:index))
130
+ end
131
+ end
132
+
133
+ If a client were to visit the index method for the first time nothing would be
134
+ displayed because the flash data isn't there yet. As soon as the client visits
135
+ /set_message he would be redirected back to the index method and the message
136
+ "Hello, Ramaze!" would be displayed. Refreshing the page would clear the flash
137
+ data and the message would no longer be displayed until the client visits
138
+ /set\_message again.
139
+
140
+ [the flash]: http://en.wikipedia.org/wiki/The_Flash_(comic_book)