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.
- 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,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
|
+

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