ramaze 2011.07.25 → 2011.10.23

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 (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)