ramaze 2011.07.25 → 2011.10.23
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +3 -0
- data/.mailmap +3 -2
- data/.travis.yml +17 -0
- data/.yardopts +13 -0
- data/README.md +95 -352
- data/examples/app/blog/app.rb +25 -64
- data/examples/app/blog/config.ru +11 -9
- data/examples/app/blog/controller/init.rb +29 -86
- data/examples/app/blog/controller/posts.rb +232 -0
- data/examples/app/blog/controller/users.rb +160 -0
- data/examples/app/blog/layout/default.xhtml +61 -0
- data/examples/app/blog/migrations/01_create_schema.rb +50 -0
- data/examples/app/blog/model/comment.rb +41 -54
- data/examples/app/blog/model/init.rb +41 -13
- data/examples/app/blog/model/post.rb +35 -0
- data/examples/app/blog/model/user.rb +105 -0
- data/examples/app/blog/public/.htaccess +24 -0
- data/examples/app/blog/public/css/grid.css +107 -0
- data/examples/app/blog/public/css/layout.css +203 -0
- data/examples/app/blog/public/css/reset.css +123 -0
- data/examples/app/blog/public/css/text.css +109 -0
- data/examples/app/blog/public/dispatch.fcgi +11 -0
- data/examples/app/blog/public/favicon.ico +0 -0
- data/examples/app/blog/public/images/bg.png +0 -0
- data/examples/app/blog/start.rb +18 -3
- data/examples/app/blog/view/feed.xhtml +23 -0
- data/examples/app/blog/view/form.xhtml +11 -0
- data/examples/app/blog/view/index.xhtml +44 -0
- data/examples/app/blog/view/users/form.xhtml +12 -0
- data/examples/app/blog/view/users/index.xhtml +30 -0
- data/examples/app/blog/view/users/login.xhtml +8 -0
- data/examples/app/blog/view/view.xhtml +68 -0
- data/{doc → guide}/AUTHORS +5 -3
- data/{doc → guide}/CHANGELOG +428 -0
- data/{doc/GPL → guide/GPL_LICENSE} +0 -0
- data/{doc/COPYING → guide/RUBY_LICENSE} +3 -6
- data/guide/_static/logo.png +0 -0
- data/guide/_static/logo.svg +49 -0
- data/guide/_static/ramaze_console.png +0 -0
- data/guide/css/common.css +20 -0
- data/guide/general/cache.md +167 -0
- data/guide/general/configuration.md +168 -0
- data/guide/general/contributing.md +108 -0
- data/guide/general/controllers.md +115 -0
- data/guide/general/helpers.md +76 -0
- data/guide/general/installation.md +58 -0
- data/guide/general/logging.md +99 -0
- data/guide/general/middlewares.md +100 -0
- data/guide/general/models.md +78 -0
- data/guide/general/principles.md +53 -0
- data/guide/general/ramaze_command.md +155 -0
- data/guide/general/routes.md +81 -0
- data/guide/general/sessions.md +140 -0
- data/guide/general/special_thanks.md +67 -0
- data/guide/general/testing.md +61 -0
- data/guide/general/views.md +322 -0
- data/guide/tutorials/introduction.md +259 -0
- data/lib/proto/config.ru +1 -1
- data/lib/proto/public/favicon.ico +0 -0
- data/lib/proto/view/index.xhtml +7 -7
- data/lib/ramaze.rb +4 -4
- data/lib/ramaze/app.rb +11 -11
- data/lib/ramaze/app_graph.rb +2 -4
- data/lib/ramaze/bin/console.rb +3 -3
- data/lib/ramaze/bin/create.rb +2 -2
- data/lib/ramaze/bin/restart.rb +4 -4
- data/lib/ramaze/bin/runner.rb +5 -5
- data/lib/ramaze/bin/start.rb +19 -4
- data/lib/ramaze/bin/status.rb +3 -3
- data/lib/ramaze/bin/stop.rb +3 -3
- data/lib/ramaze/cache.rb +1 -0
- data/lib/ramaze/cache/lru.rb +8 -4
- data/lib/ramaze/cache/memcache.rb +32 -13
- data/lib/ramaze/cache/redis.rb +164 -0
- data/lib/ramaze/cache/sequel.rb +43 -28
- data/lib/ramaze/controller.rb +1 -2
- data/lib/ramaze/dependencies.rb +40 -3
- data/lib/ramaze/helper/bench.rb +26 -16
- data/lib/ramaze/helper/blue_form.rb +46 -73
- data/lib/ramaze/helper/cache.rb +10 -6
- data/lib/ramaze/helper/csrf.rb +35 -39
- data/lib/ramaze/helper/disqus.rb +5 -4
- data/lib/ramaze/helper/email.rb +35 -24
- data/lib/ramaze/helper/erector.rb +9 -13
- data/lib/ramaze/helper/flash.rb +7 -9
- data/lib/ramaze/helper/formatting.rb +194 -179
- data/lib/ramaze/helper/gravatar.rb +4 -8
- data/lib/ramaze/helper/identity.rb +3 -3
- data/lib/ramaze/helper/layout.rb +23 -8
- data/lib/ramaze/helper/markaby.rb +1 -1
- data/lib/ramaze/helper/paginate.rb +46 -39
- data/lib/ramaze/helper/request_accessor.rb +3 -1
- data/lib/ramaze/helper/simple_captcha.rb +18 -17
- data/lib/ramaze/helper/stack.rb +1 -1
- data/lib/ramaze/helper/tagz.rb +4 -2
- data/lib/ramaze/helper/upload.rb +523 -0
- data/lib/ramaze/helper/user.rb +4 -8
- data/lib/ramaze/helper/xhtml.rb +11 -15
- data/lib/ramaze/log.rb +9 -6
- data/lib/ramaze/log/rotatinginformer.rb +62 -27
- data/lib/ramaze/log/syslog.rb +20 -15
- data/lib/ramaze/log/xosd.rb +2 -1
- data/lib/ramaze/reloader.rb +2 -0
- data/lib/ramaze/request.rb +11 -10
- data/lib/ramaze/setup.rb +23 -6
- data/lib/ramaze/snippets/array/put_within.rb +3 -9
- data/lib/ramaze/snippets/binding/locals.rb +5 -10
- data/lib/ramaze/snippets/fiber.rb +1 -23
- data/lib/ramaze/snippets/kernel/pretty_inspect.rb +3 -6
- data/lib/ramaze/snippets/numeric/filesize_format.rb +3 -5
- data/lib/ramaze/snippets/numeric/time.rb +3 -7
- data/lib/ramaze/snippets/object/__dir__.rb +3 -7
- data/lib/ramaze/snippets/object/instance_variable_defined.rb +3 -6
- data/lib/ramaze/snippets/object/pretty.rb +3 -7
- data/lib/ramaze/snippets/object/scope.rb +7 -9
- data/lib/ramaze/snippets/proc/locals.rb +12 -12
- data/lib/ramaze/snippets/ramaze/acquire.rb +15 -14
- data/lib/ramaze/snippets/ramaze/deprecated.rb +1 -1
- data/lib/ramaze/snippets/ramaze/fiber.rb +1 -1
- data/lib/ramaze/snippets/ramaze/lru_hash.rb +2 -3
- data/lib/ramaze/snippets/ramaze/struct.rb +2 -4
- data/lib/ramaze/snippets/string/camel_case.rb +8 -10
- data/lib/ramaze/snippets/string/color.rb +3 -4
- data/lib/ramaze/snippets/string/end_with.rb +3 -6
- data/lib/ramaze/snippets/string/esc.rb +3 -8
- data/lib/ramaze/snippets/string/ord.rb +3 -8
- data/lib/ramaze/snippets/string/snake_case.rb +6 -9
- data/lib/ramaze/snippets/string/start_with.rb +3 -8
- data/lib/ramaze/snippets/string/unindent.rb +3 -6
- data/lib/ramaze/snippets/thread/into.rb +1 -3
- data/lib/ramaze/spec.rb +2 -31
- data/lib/ramaze/spec/bacon.rb +18 -2
- data/lib/ramaze/version.rb +1 -1
- data/lib/ramaze/view.rb +1 -1
- data/ramaze.gemspec +1 -1
- data/spec/helper.rb +2 -1
- data/spec/ramaze/bin/start.rb +16 -20
- data/spec/ramaze/cache/localmemcache.rb +4 -7
- data/spec/ramaze/cache/memcache.rb +3 -1
- data/spec/ramaze/cache/redis.rb +62 -0
- data/spec/ramaze/helper/blue_form.rb +33 -4
- data/spec/ramaze/helper/layout.rb +40 -7
- data/spec/ramaze/helper/upload.rb +149 -0
- data/spec/ramaze/helper/uploads/text_1.txt +1 -0
- data/spec/ramaze/helper/uploads/text_2.txt +1 -0
- data/spec/ramaze/log/growl.rb +4 -6
- data/spec/ramaze/log/syslog.rb +6 -0
- data/spec/ramaze/view/lokar.rb +5 -0
- data/spec/ramaze/view/nagoro.rb +5 -0
- data/tasks/authors.rake +1 -1
- data/tasks/bacon.rake +14 -5
- data/tasks/changelog.rake +1 -1
- data/tasks/yard.rake +12 -4
- metadata +277 -239
- data/doc/LEGAL +0 -26
- data/examples/app/blog/README +0 -3
- data/examples/app/blog/controller/comment.rb +0 -45
- data/examples/app/blog/controller/entry.rb +0 -85
- data/examples/app/blog/controller/main.rb +0 -20
- data/examples/app/blog/controller/tag.rb +0 -9
- data/examples/app/blog/layout/default.nag +0 -31
- data/examples/app/blog/model/entry.rb +0 -89
- data/examples/app/blog/model/tag.rb +0 -36
- data/examples/app/blog/public/css/screen.css +0 -273
- data/examples/app/blog/spec/blog.rb +0 -87
- data/examples/app/blog/view/comment/form.nag +0 -10
- data/examples/app/blog/view/comment/show.nag +0 -16
- data/examples/app/blog/view/entry/edit.nag +0 -14
- data/examples/app/blog/view/entry/feed.atom.nag +0 -8
- data/examples/app/blog/view/entry/feed.rss.nag +0 -7
- data/examples/app/blog/view/entry/index.nag +0 -7
- data/examples/app/blog/view/entry/new.nag +0 -13
- data/examples/app/blog/view/entry/show.nag +0 -36
- data/examples/app/blog/view/feed.atom.nag +0 -18
- data/examples/app/blog/view/feed.rss.nag +0 -25
- data/examples/app/blog/view/index.nag +0 -6
- data/examples/app/blog/view/tag/index.nag +0 -5
- data/lib/proto/public/ramaze.png +0 -0
- data/lib/ramaze/rest.rb +0 -36
- data/spec/ramaze/rest.rb +0 -28
- 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}.
|