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,115 @@
1
+ # Controllers
2
+
3
+ When developing web applications controllers are the elements that are called
4
+ by a browser. When visiting a page a request is made that is processed by Rack
5
+ and sent to Ramaze. Ramaze in turn will determine what controller to call.
6
+
7
+ To make understanding controllers a bit easier will use a real world example.
8
+ Let's say we're in a restaurant and want to order some food. The waiter of the
9
+ restaurant can be seen as a controller. We'll talk to it and tell him what we
10
+ want to have for dinner but the waiter itself won't actually prepare our dinner,
11
+ instead it will merely tell the cooks to make the dinner and bring it to you once
12
+ it's done. The waiter is our controller, the cook is our model and our meal can
13
+ be seen as the view.
14
+
15
+ In a typical application the entire flow of a request is as following::
16
+
17
+ Request --> Server (Thin, Unicorn, etc) --> Rack --> Ramaze --> Controller
18
+
19
+ ## Ramaze & Controllers
20
+
21
+ In Ramaze controllers are plain Ruby classes that extend Ramaze::Controller. The
22
+ most basic controller looks like the following:
23
+
24
+ class ControllerName < Ramaze::Controller
25
+ map '/uri'
26
+
27
+ def index
28
+
29
+ end
30
+ end
31
+
32
+ Let's walk through this snippet step by step. The first line declares a new
33
+ class that extends Ramaze::Controller. Extending this base class is very
34
+ important, without it we won't be able to call controller specific methods such
35
+ as the map() method. This method, which is called on line 2, is used to instruct
36
+ Ramaze what controller is bound to what URI(Uniform Resource Identifier). The
37
+ argument of this method should be a string starting with a /. The reason for
38
+ this is that the URIs are relative to URL the application is running on. For
39
+ example, if our application was running at ramaze.net a URI of "/blog" would
40
+ mean the controller can be found at ramaze.net/blog.
41
+
42
+ Let's move to the next lines of code. The next lines of code define a new method
43
+ called "index". By default Ramaze will try to call this method if no URI after
44
+ the mapped URI is given. In our /blog example a call to ramaze.net/blog would
45
+ call BlogController#index but a call to ramaze.net/blog/entry/10 would call
46
+ BlogController#entry(10).
47
+
48
+ All methods that are declared as public can be accessed by a user and by default
49
+ the index() method is called if no other method is specified. Don't like the
50
+ index() method? No problem, you can specify a different default method to call
51
+ as following:
52
+
53
+ class ControllerName < Ramaze::Controller
54
+ trait :default_action_name => 'default'
55
+
56
+ def default
57
+
58
+ end
59
+ end
60
+
61
+ We're not going to cover Traits too much in this chapter as there's a dedicated
62
+ chapter for them but in short they're a way of setting configuration options. In
63
+ this case we're using the trait "default_action_name" to specify what the name
64
+ of the default method should be. By default this is set to "index" but in the
65
+ above example it was changed to "default".
66
+
67
+ ## Registering Controllers
68
+
69
+ By now you might be thinking "How does Ramaze know what controller to call? I
70
+ didn't initialize the controller!". It's true, you don't have to manually
71
+ initialize the controller and save it in a hash or somewhere else. The entire
72
+ process of registering a controller is done by the map() method and thus is one
73
+ of the most important methods available. When calling this method it will store
74
+ the name of the class that invoked it and bind it to the given URI. Whenever a
75
+ request is made Ramaze simply creates an instance of the matching controller
76
+ for a given URI.
77
+
78
+ The basic process of the map() method is as following:
79
+
80
+ 1. Call map().
81
+ 2. Validate the given URI.
82
+ 3. Store the controller constant.
83
+ 4. Done.
84
+
85
+ ## Base Controllers
86
+
87
+ In many applications you'll have separate areas such as an admin panel and the
88
+ frontend. Usually you want to authenticate users for certain controllers, such
89
+ as those used for an admin panel. An easy way of doing this is by putting the
90
+ authentication call in a controller. By creating a base controller and extending
91
+ it you don't have to call the method that authenticates the user over and over
92
+ again. Because Ramaze is just Ruby all you have to do to achieve this is the
93
+ following:
94
+
95
+ class AdminController < Ramaze::Controller
96
+
97
+ end
98
+
99
+ class Users < AdminController
100
+
101
+ end
102
+
103
+ If your base controller has an initialize() method defined you should always
104
+ call the parent's initialize() method to ensure everything is working properly.
105
+ This can be done by calling super():
106
+
107
+ class AdminController < Ramaze::Controller
108
+ def initialize
109
+ # Calls Ramaze::Controller#initialize
110
+ super
111
+
112
+ # Custom calls can be placed here...
113
+ # ...
114
+ end
115
+ end
@@ -0,0 +1,76 @@
1
+ # Helpers
2
+
3
+ Helpers are simple modules that can be used in controllers to prevent developers
4
+ from having to write the same code over and over again. There's no actual
5
+ definition of how helpers should be used and what they should do but the general
6
+ idea is quite simple, all logic that may be shared among controllers should go
7
+ in a helper. For example, Ramaze ships with it's own layout helper that adds a
8
+ method ``set_layout()`` (see the {file:general/views Views} chapter).
9
+
10
+ In order to use a helper there are a few guidelines it should follow. The most
11
+ important guideline (or rule) is that it should be declared under the
12
+ Ramaze::Helper namespace. Say your helper is called "Cake" this would result in
13
+ Ramaze::Helper::Cake as the full name. The second rule/guideline is that helpers
14
+ should be placed in the "helper" directory of your Ramaze application (or any
15
+ other directory added to the list of helper paths). This is required in order to
16
+ load helpers the ramaze way, otherwise you'll have to manually load each helper.
17
+
18
+ ## Loading Helpers
19
+
20
+ Loading helpers the Ramaze way is pretty easy and can be done using the method
21
+ helper():
22
+
23
+ class Blogs < Ramaze::Controller
24
+ helper :cake
25
+ end
26
+
27
+ This method can load multiple helpers in a single call as well:
28
+
29
+ class Blogs < Ramaze::Controller
30
+ helper :cake, :pie, :candy
31
+ end
32
+
33
+ If you have your helper located somewhere else or don't want to use the helper()
34
+ method you can just include each helper the regular way:
35
+
36
+ class Blogs < Ramaze::Controller
37
+ include Ramaze::Helper::Cake
38
+ include Ramaze::Helper::Pie
39
+ include Ramaze::Helper::Candy
40
+ end
41
+
42
+ As you can see this requires more lines of code and thus it's recommended to
43
+ load all helpers the Ramaze way.
44
+
45
+ ## Available Helpers
46
+
47
+ * {Ramaze::Helper::Auth}: basic authentication without a model.
48
+ * {Ramaze::Helper::Bench}: basic benchmarking of your code.
49
+ * {Ramaze::Helper::BlueForm}: makes building forms fun again.
50
+ * {Ramaze::Helper::Cache}: caching of entire actions and custom values in your
51
+ controllers.
52
+ * {Ramaze::Helper::CSRF}: protect your controllers from CSRF attacks.
53
+ * {Ramaze::Helper::Disqus}
54
+ * {Ramaze::Helper::Email}: quick and easy way to send Emails.
55
+ * {Ramaze::Helper::Erector}
56
+ * {Ramaze::Helper::Flash}
57
+ * {Ramaze::Helper::Gestalt}: helper for {Ramaze::Gestalt}.
58
+ * {Ramaze::Helper::Gravatar}: easily generate Gravatars.
59
+ * {Ramaze::Helper::Identity}: helper for OpenID authentication.
60
+ * {Ramaze::Helper::Layout}: easily set layouts for specific actions.
61
+ * {Ramaze::Helper::Link}
62
+ * {Ramaze::Helper::Localize}
63
+ * {Ramaze::Helper::Markaby}
64
+ * {Ramaze::Helper::Maruku}
65
+ * {Ramaze::Helper::Paginate}: easily paginate rows of data.
66
+ * {Ramaze::Helper::Remarkably}
67
+ * {Ramaze::Helper::RequestAccessor}
68
+ * {Ramaze::Helper::SendFile}
69
+ * {Ramaze::Helper::SimpleCaptcha}: captches using simple mathematical questions.
70
+ * {Ramaze::Helper::Stack}
71
+ * {Ramaze::Helper::Tagz}
72
+ * {Ramaze::Helper::Thread}
73
+ * {Ramaze::Helper::Ultraviolet}
74
+ * {Ramaze::Helper::Upload}: uploading files made easy.
75
+ * {Ramaze::Helper::UserHelper}: authenticate users using a model.
76
+ * {Ramaze::Helper::XHTML}
@@ -0,0 +1,58 @@
1
+ # Installation
2
+
3
+ Ramaze can be installed by using [Rubygems][rubygems], direct download or by
4
+ using Git. Installing Ramaze via Rubygems only needs a single command:
5
+
6
+ $ gem install ramaze
7
+
8
+ Optionally you can specify ``-v`` to install a specific version:
9
+
10
+ $ gem install ramaze -v 2011.07.25
11
+
12
+ ## Git
13
+
14
+ If you're interested in hacking on Ramaze or you just want to browse the source
15
+ you can use Git to install a local copy of Ramaze. For this you'll need to have
16
+ Git installed (refer to your package manager for details on installing Git).
17
+ When installed you can clone the Ramaze repository with the following commnad:
18
+
19
+ $ git clone git://github.com/ramaze/ramaze.git
20
+
21
+ Once the cloning process has completed you should ``cd`` into the directory to
22
+ install all required gems and optionally set up an RVM environment in case
23
+ you're using RVM:
24
+
25
+ $ cd ramaze
26
+ $ rake setup
27
+
28
+ Once installed you can build a gem manually or just require the local
29
+ installation manually:
30
+
31
+ require '/path/to/ramaze/lib/ramaze'
32
+
33
+ Building a gem can be done using the command ``rake gem:build``, if you want to
34
+ also install the gem after it's built you should run ``rake gem:install``
35
+ instead.
36
+
37
+ Another way of loading Ramaze is to add it to your ``$RUBYLIB`` variable. It's
38
+ best if you put this in your ``.bashrc`` file so that you don't have to run the
39
+ command manually every time you open up a new terminal:
40
+
41
+ export RUBYLIB="/path/to/ramaze/lib"
42
+
43
+ This approach allows you to load Ramaze like you'd normally would instead of
44
+ having to specify the full path.
45
+
46
+ ## Direct Download
47
+
48
+ In case you don't have Git installed but still want to have a local copy you can
49
+ download a tarball from Github. If you want to download the latest copy you can
50
+ go to the [Downloads][downloads] page, if you want to download a specific tag
51
+ instead you should navigate to the [Tags][tags] page.
52
+
53
+ Once downloaded and extracted the setup process is the same as when installing
54
+ Ramaze via Git.
55
+
56
+ [rubygems]: http://rubygems.org/
57
+ [downloads]: https://github.com/Ramaze/ramaze/downloads
58
+ [tags]: https://github.com/Ramaze/ramaze/tags
@@ -0,0 +1,99 @@
1
+ # Logging
2
+
3
+ Similar to the caching system Ramaze makes it easy to log information using a
4
+ unified API, whether you're logging to a file, using Growl or something else.
5
+ Ramaze itself only uses a single logger which logs to STDOUT by default. This
6
+ logger is stored in ``Ramaze::Log``. While you can just use this particular
7
+ logger it's recommended to create your own ones if you need to log specific
8
+ types of data (such as API calls).
9
+
10
+ Creating a custom logger works just like initializing a regular class. Say you
11
+ want to rotate your log files based on the current date, in that case
12
+ {Ramaze::Logger::RotatingInformer} should be used. To use this logger you'd
13
+ simply do the following:
14
+
15
+ logger = Ramaze::Logger::RotatingInformer.new('./log')
16
+
17
+ This creates a new instance of the logger and tells it to store it's log files
18
+ in the ``./log`` directory. Each log file's name is the date on which it was
19
+ created in the format of ``yyyy-mm-dd``.
20
+
21
+ Once a logger has been created you can use the following logging methods:
22
+
23
+ * warn: logs a warning message.
24
+ * debug: logs a debugging message such as "Connected to the database".
25
+ * error: logs an error message, useful for logging validation errors and the
26
+ like.
27
+ * info: logging method for generic log messages that don't fit into a specific
28
+ category.
29
+
30
+ You can call these methods on the instance of a logger just like any other
31
+ method:
32
+
33
+ logger.info 'Logging data sure is easy to do!'
34
+
35
+ ## Creating Custom Loggers
36
+
37
+ Ramaze provides an API that makes it easy to create your own logging class. Each
38
+ log class should include the module {Ramaze::Logging}, this module provides the
39
+ basic setup for every logger and stops you from having to re-invent the wheel
40
+ every time.
41
+
42
+ class MyLogger
43
+ include Ramaze::Logging
44
+ end
45
+
46
+ Each logger should respond to the instance method ``log()``. This method will be
47
+ used by other methods such as ``error()`` and ``warn()``, therefor your logger
48
+ is somewhat useless without this method. The ``log()`` method should take at
49
+ least two parameters, the first one the logging level (such as "error") and the
50
+ second (and all following parameters) should be messages to log. Lets add this
51
+ method to the ``MyLogger`` class shown above:
52
+
53
+ class MyLogger
54
+ include Ramaze::Logging
55
+
56
+ def log(level, *messages)
57
+
58
+ end
59
+ end
60
+
61
+ Now you no longer get nasty errors when trying to log data. However, your data
62
+ is also completely ignored (after all, the method isn't doing anything yet).
63
+ What the ``log()`` method does is really up to you, whether you're logging to
64
+ STDOUT, to a file or to a database. A basic example of logging to STDOUT using
65
+ this class can be seen below.
66
+
67
+ class MyLogger
68
+ include Ramaze::Logging
69
+
70
+ def log(level, *messages)
71
+ messages.each do |message|
72
+ $stdout.puts "#{level.upcase}: #{message}"
73
+ end
74
+ end
75
+ end
76
+
77
+ When using this class the output will look like the following:
78
+
79
+ ruby-1.9.2-p290 :011 > logger = MyLogger.new
80
+ => #<MyLogger:0x00000101ae6328>
81
+ ruby-1.9.2-p290 :011 > logger.info 'Hello Ramaze!'
82
+ INFO: Hello Ramaze!
83
+
84
+ Of course it doesn't stop here. You can add colors, timestamps and pretty much
85
+ whatever you want.
86
+
87
+ ## Available Loggers
88
+
89
+ * {Ramaze::Logger::Analogger}
90
+ * {Ramaze::Logger::Growl}: uses Growl for log messages (requires Mac OS).
91
+ * {Ramaze::Logger::LogHub}
92
+ * {Ramaze::Logger::Informer}
93
+ * {Ramaze::Logger::Knotify}
94
+ * {Ramaze::Logger::Logger}: wrapper around the Logger class from the Stdlib.
95
+ * {Ramaze::Logging}: basic skeleton for your own loggers.
96
+ * {Ramaze::Logger::RotatingInformer}: logger that rotates log files based on the
97
+ current date.
98
+ * {Ramaze::Logger::Syslog}: logger that uses syslog.
99
+ * {Ramaze::Logger::Xosd}
@@ -0,0 +1,100 @@
1
+ # Rack Middlewares
2
+
3
+ Ramaze is a Rack based framework and thus allows you to create so called
4
+ middlewares. Middlewares are basically classes that can be used to intercept the
5
+ communication between Rack, Ramaze and the visitor as well as providing common
6
+ functionality such as logging of requests. The flow of a Rack request (including
7
+ middlewares) looks as following::
8
+
9
+ Request --> Server (Thin, Unicorn, etc) --> Rack --> Middleware(s) -->
10
+ Ramaze --> Controller
11
+
12
+ Say we want to ban a number of users by IP, there are two ways of doing this.
13
+ The first way of doing this would be to validate the user's IP in all controllers
14
+ (or in a base controller). However, this approach will eventually require quite
15
+ a bit of code. The easier method, as you may have guessed, is using a Rack
16
+ middleware. Since middlewares are executed for each request this means we'll
17
+ only have to add our code once and we're good to go.
18
+
19
+ ## Building the Middleware
20
+
21
+ Let's begin building our IP blacklist. For the sake of simplicity we'll hardcode
22
+ the blocked IPs in an array stored inside our middleware. Go ahead and create a
23
+ file called "banlist.rb" and save it somewhere in your application (and require
24
+ it!). We'll begin with our basic skeleton that looks like the following:
25
+
26
+ class Banlist
27
+ def initialize(app)
28
+ @app = app
29
+ end
30
+
31
+ def call(env)
32
+
33
+ end
34
+ end
35
+
36
+ First we declare a new class called "Banlist". Followed by this is our construct
37
+ method that takes a single argument: an object containing the details of our
38
+ Ramaze application. Next up is the call() method which also takes a single
39
+ argument but this time it's an object containing our environment details such as
40
+ the POST and GET data.
41
+
42
+ Let's add a list of blocked IPs to our middleware. Modify the initialize()
43
+ method so that it looks like the following:
44
+
45
+ def initialize(app)
46
+ @app = app
47
+ @banned = ['189.3.0.116', '193.159.244.70', '193.46.236.*']
48
+ end
49
+
50
+ We now have 3 blocked IPs. Time to actually implement the blocking mechanism in
51
+ our call() method. Modify it as following:
52
+
53
+ def call(env)
54
+ if @banned.include?(env['REMOTE_ADDR'])
55
+ return "You have been banned!"
56
+ else
57
+ @app.call(env)
58
+ end
59
+ end
60
+
61
+ So what did we do? Quite simple actually, we extracted the user's IP by calling
62
+ ``env['REMOTE_ADDR']`` and checked if it's stored in the @banned instance
63
+ variable. If it is we'll block the user and show a message "You have been
64
+ banned". Our final middleware looks like the following:
65
+
66
+ class Banlist
67
+ def initialize(app)
68
+ @app = app
69
+ @banned = ['189.3.0.116', '193.159.244.70', '193.46.236.10']
70
+ end
71
+
72
+ def call(env)
73
+ if @banned.include?(env['REMOTE_ADDR'])
74
+ return "You have been banned!"
75
+ else
76
+ @app.call(env)
77
+ end
78
+ end
79
+ end
80
+
81
+ ## Using Middlewares
82
+
83
+ Now it's time to tell Ramaze to actually use the middleware. This can be done
84
+ by calling Ramaze#middleware!. This method takes a block that defines what
85
+ middlewares to use for what environment. Assuming we're dunning in "dev" mode
86
+ our call will look like the following:
87
+
88
+ Ramaze.middleware! :dev do |m|
89
+ m.use(Banlist)
90
+ m.run(Ramaze::AppMap)
91
+ end
92
+
93
+ When calling the ``middleware!()`` method it's first argument should be a
94
+ development mode to use (Ramaze comes with "live" and "dev"), the method also
95
+ accepts a block which is used to determine what middlewares to use and to run
96
+ Ramaze ({Ramaze::AppMap}). In this block you can call two methods, use() and
97
+ run(). The first method is used to add a middleware and configure it, the run()
98
+ method is used to determine what class is used to run our Ramaze application.
99
+ Unless you're using a custom class this should always be set to
100
+ {Ramaze::AppMap}.