camping 2.0 → 2.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +11 -0
- data/Rakefile +21 -3
- data/bin/camping +2 -85
- data/book/51_upgrading +17 -0
- data/lib/camping-unabridged.rb +56 -16
- data/lib/camping.rb +37 -32
- data/lib/camping/mab.rb +2 -0
- data/lib/camping/reloader.rb +39 -45
- data/lib/camping/server.rb +217 -130
- data/lib/camping/session.rb +5 -6
- data/lib/camping/template.rb +17 -0
- data/test/app_markup.rb +51 -0
- data/test/app_route_generating.rb +22 -0
- data/test/app_sessions.rb +46 -0
- data/test/app_simple.rb +97 -0
- data/test/test_helper.rb +51 -0
- metadata +9 -16
- data/doc/api.html +0 -1953
- data/doc/book.html +0 -73
- data/doc/book/01_introduction.html +0 -57
- data/doc/book/02_getting_started.html +0 -573
- data/doc/book/51_upgrading.html +0 -146
- data/doc/created.rid +0 -1
- data/doc/images/Camping.gif +0 -0
- data/doc/images/loadingAnimation.gif +0 -0
- data/doc/images/permalink.gif +0 -0
- data/doc/index.html +0 -148
- data/doc/js/camping.js +0 -79
- data/doc/js/jquery.js +0 -32
- data/doc/rdoc.css +0 -117
data/doc/book.html
DELETED
@@ -1,73 +0,0 @@
|
|
1
|
-
<!DOCTYPE html>
|
2
|
-
<html>
|
3
|
-
<head>
|
4
|
-
<title>Camping, a Microframework</title>
|
5
|
-
<link rel="stylesheet" href="./rdoc.css" type="text/css" media="screen" />
|
6
|
-
<script src="./js/jquery.js" type="text/javascript"></script>
|
7
|
-
<script src="js/camping.js" type="text/javascript"></script>
|
8
|
-
</head>
|
9
|
-
<body>
|
10
|
-
<div id="menu">
|
11
|
-
<ul id="links">
|
12
|
-
<li><a href="./index.html">front</a> | </li>
|
13
|
-
<li><a href="./api.html">reference</a> | </li>
|
14
|
-
<li><a href="http://wiki.github.com/camping/camping">wiki</a> | </li>
|
15
|
-
<li><a href="http://github.com/camping/camping">code</a></li>
|
16
|
-
</ul>
|
17
|
-
<p id="version">Camping 2.0</p>
|
18
|
-
</div>
|
19
|
-
|
20
|
-
<div id="fullpage">
|
21
|
-
<div class="page_shade">
|
22
|
-
<div class="page">
|
23
|
-
<p class="header">Fri Apr 09 16:33:39 +0200 2010</p>
|
24
|
-
<h1>Camping, the Book</h1>
|
25
|
-
<ol>
|
26
|
-
|
27
|
-
<li>
|
28
|
-
<a href="book/01_introduction.html">Introduction</a>
|
29
|
-
|
30
|
-
</li>
|
31
|
-
|
32
|
-
<li>
|
33
|
-
<a href="book/02_getting_started.html">Getting Started</a>
|
34
|
-
|
35
|
-
<ul>
|
36
|
-
|
37
|
-
<li><a href="book/02_getting_started.html#hello-clock">Hello clock</a></li>
|
38
|
-
|
39
|
-
<li><a href="book/02_getting_started.html#enjoying-the-view">Enjoying the view</a></li>
|
40
|
-
|
41
|
-
<li><a href="book/02_getting_started.html#routes">Routes</a></li>
|
42
|
-
|
43
|
-
<li><a href="book/02_getting_started.html#modeling-the-world">Modeling the world</a></li>
|
44
|
-
|
45
|
-
<li><a href="book/02_getting_started.html#using-our-model">Using our model</a></li>
|
46
|
-
|
47
|
-
<li><a href="book/02_getting_started.html#wrapping-it-up">Wrapping it up</a></li>
|
48
|
-
|
49
|
-
<li><a href="book/02_getting_started.html#the-last-touch">The last touch</a></li>
|
50
|
-
|
51
|
-
<li><a href="book/02_getting_started.html#phew">Phew.</a></li>
|
52
|
-
|
53
|
-
</ul>
|
54
|
-
|
55
|
-
</li>
|
56
|
-
|
57
|
-
<li>
|
58
|
-
<a href="book/51_upgrading.html">Appendix I: Upgrade Notes</a>
|
59
|
-
|
60
|
-
<ul>
|
61
|
-
|
62
|
-
<li><a href="book/51_upgrading.html#from-15-to-20">From 1.5 to 2.0</a></li>
|
63
|
-
|
64
|
-
</ul>
|
65
|
-
|
66
|
-
</li>
|
67
|
-
|
68
|
-
</ol>
|
69
|
-
</div>
|
70
|
-
</div>
|
71
|
-
</div>
|
72
|
-
</body>
|
73
|
-
</html>
|
@@ -1,57 +0,0 @@
|
|
1
|
-
<!DOCTYPE html>
|
2
|
-
<html>
|
3
|
-
<head>
|
4
|
-
<title>Camping, a Microframework</title>
|
5
|
-
<link rel="stylesheet" href="../rdoc.css" type="text/css" media="screen" />
|
6
|
-
<script src="../js/jquery.js" type="text/javascript"></script>
|
7
|
-
<script src="../js/camping.js" type="text/javascript"></script>
|
8
|
-
</head>
|
9
|
-
<body>
|
10
|
-
<div id="menu">
|
11
|
-
<ul id="links">
|
12
|
-
<li><a href="../index.html">front</a> | </li>
|
13
|
-
<li><a href="../book.html">ToC</a> | </li>
|
14
|
-
<li><a href="../api.html">reference</a> | </li>
|
15
|
-
<li><a href="http://wiki.github.com/camping/camping">wiki</a> | </li>
|
16
|
-
<li><a href="http://github.com/camping/camping">code</a></li>
|
17
|
-
</ul>
|
18
|
-
<p id="version">Camping 2.0</p>
|
19
|
-
</div>
|
20
|
-
|
21
|
-
<div id="fullpage">
|
22
|
-
<div class="page_shade">
|
23
|
-
<div class="page">
|
24
|
-
<p class="header">Fri Apr 09 16:33:39 +0200 2010</p>
|
25
|
-
<h1>Introduction</h1>
|
26
|
-
<p>
|
27
|
-
<a href="../api.html#class-Camping">Camping</a> is a small web framework,
|
28
|
-
less than 4k, a little white blood cell in the vein of Rails. This little
|
29
|
-
book will start with a tutorial which takes about fifteen minutes - by the
|
30
|
-
end you should have a little <a
|
31
|
-
href="../api.html#class-Camping">Camping</a> site up. The following
|
32
|
-
chapters will eventually go deeper into how both <a
|
33
|
-
href="../api.html#class-Camping">Camping</a>, HTTP and Rack works.
|
34
|
-
</p>
|
35
|
-
<p>
|
36
|
-
(“Eventually”, because these chapters are not written yet. This
|
37
|
-
book is currently a very much work in progress, and we’ll be very
|
38
|
-
grateful if you want to help out.)
|
39
|
-
</p>
|
40
|
-
<p>
|
41
|
-
If you at any moment need some help or have any questions or comments, we
|
42
|
-
highly recommend <a
|
43
|
-
href="http://rubyforge.org/mailman/listinfo/camping-list">the mailing
|
44
|
-
list</a> which got plenty of nice people willing to help. We also have an
|
45
|
-
IRC-channel at <a href="http://java.freenode.net/?channel=camping">#camping
|
46
|
-
@ irc.freenode.net</a> if you’re into that sort of things.
|
47
|
-
</p>
|
48
|
-
<p>
|
49
|
-
Enough talk. Ready? Let’s <a href="02_getting_started.html">"get
|
50
|
-
started"</a>.
|
51
|
-
</p>
|
52
|
-
|
53
|
-
</div>
|
54
|
-
</div>
|
55
|
-
</div>
|
56
|
-
</body>
|
57
|
-
</html>
|
@@ -1,573 +0,0 @@
|
|
1
|
-
<!DOCTYPE html>
|
2
|
-
<html>
|
3
|
-
<head>
|
4
|
-
<title>Camping, a Microframework</title>
|
5
|
-
<link rel="stylesheet" href="../rdoc.css" type="text/css" media="screen" />
|
6
|
-
<script src="../js/jquery.js" type="text/javascript"></script>
|
7
|
-
<script src="../js/camping.js" type="text/javascript"></script>
|
8
|
-
</head>
|
9
|
-
<body>
|
10
|
-
<div id="menu">
|
11
|
-
<ul id="links">
|
12
|
-
<li><a href="../index.html">front</a> | </li>
|
13
|
-
<li><a href="../book.html">ToC</a> | </li>
|
14
|
-
<li><a href="../api.html">reference</a> | </li>
|
15
|
-
<li><a href="http://wiki.github.com/camping/camping">wiki</a> | </li>
|
16
|
-
<li><a href="http://github.com/camping/camping">code</a></li>
|
17
|
-
</ul>
|
18
|
-
<p id="version">Camping 2.0</p>
|
19
|
-
</div>
|
20
|
-
|
21
|
-
<div id="fullpage">
|
22
|
-
<div class="page_shade">
|
23
|
-
<div class="page">
|
24
|
-
<p class="header">Fri Apr 09 16:33:39 +0200 2010</p>
|
25
|
-
<h1>Getting Started</h1>
|
26
|
-
<p>
|
27
|
-
Start a new text file called nuts.rb. Here’s what you put inside:
|
28
|
-
</p>
|
29
|
-
<pre>
|
30
|
-
Camping.goes :Nuts
|
31
|
-
</pre>
|
32
|
-
<p>
|
33
|
-
Save it. Then, open a command prompt in the same directory. You’ll
|
34
|
-
want to run:
|
35
|
-
</p>
|
36
|
-
<pre>
|
37
|
-
$ camping nuts.rb
|
38
|
-
</pre>
|
39
|
-
<p>
|
40
|
-
And you should get a message which reads:
|
41
|
-
</p>
|
42
|
-
<pre>
|
43
|
-
** Camping running on 0.0.0.0:3301.
|
44
|
-
</pre>
|
45
|
-
<p>
|
46
|
-
This means that right now The <a
|
47
|
-
href="../api.html#class-Camping">Camping</a> Server is running on port 3301
|
48
|
-
on your machine. Open your browser and visit <a
|
49
|
-
href="http://localhost:3301/.">localhost:3301/.</a>
|
50
|
-
</p>
|
51
|
-
<p>
|
52
|
-
Your browser window should show:
|
53
|
-
</p>
|
54
|
-
<pre>
|
55
|
-
Camping Problem!
|
56
|
-
|
57
|
-
/ Not found
|
58
|
-
</pre>
|
59
|
-
<p>
|
60
|
-
No problem with that. The <a href="../api.html#class-Camping">Camping</a>
|
61
|
-
Server is running, but it doesn’t know what to show. Let’s tell
|
62
|
-
him.
|
63
|
-
</p>
|
64
|
-
<h2 class="ruled" id="hello-clock">Hello clock</h2>
|
65
|
-
<p>
|
66
|
-
So, you’ve got <a href="../api.html#class-Camping">Camping</a>
|
67
|
-
installed and it’s running. Keep it running. You can edit files and
|
68
|
-
The <a href="../api.html#class-Camping">Camping</a> Server will reload
|
69
|
-
automatically. When you need to stop the server, press Control-C.
|
70
|
-
</p>
|
71
|
-
<p>
|
72
|
-
Let’s show something. At the bottom of nuts.rb add:
|
73
|
-
</p>
|
74
|
-
<pre>
|
75
|
-
module Nuts::Controllers
|
76
|
-
class Index < R '/'
|
77
|
-
def get
|
78
|
-
Time.now.to_s
|
79
|
-
end
|
80
|
-
end
|
81
|
-
end
|
82
|
-
</pre>
|
83
|
-
<p>
|
84
|
-
Save the file and refresh the browser window. Your browser window should
|
85
|
-
show the time, e.g.
|
86
|
-
</p>
|
87
|
-
<pre>
|
88
|
-
Sun Jul 15 12:56:15 +0200 2007
|
89
|
-
</pre>
|
90
|
-
<h2 class="ruled" id="enjoying-the-view">Enjoying the view</h2>
|
91
|
-
<p>
|
92
|
-
The <a href="../api.html#class-Camping">Camping</a> microframework allows
|
93
|
-
us to separate our code using the MVC (Model-View-Controller) design
|
94
|
-
pattern. Let’s add a view to our Nuts application. Replace the
|
95
|
-
<tt>module Nuts::Controllers</tt> with:
|
96
|
-
</p>
|
97
|
-
<pre>
|
98
|
-
module Nuts::Controllers
|
99
|
-
class Index < R '/'
|
100
|
-
def get
|
101
|
-
@time = Time.now
|
102
|
-
render :sundial
|
103
|
-
end
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
107
|
-
module Nuts::Views
|
108
|
-
def layout
|
109
|
-
html do
|
110
|
-
head do
|
111
|
-
title { "Nuts And GORP" }
|
112
|
-
end
|
113
|
-
body { self << yield }
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
|
-
def sundial
|
118
|
-
p "The current time is: #{@time}"
|
119
|
-
end
|
120
|
-
end
|
121
|
-
</pre>
|
122
|
-
<p>
|
123
|
-
Save the file and refresh your browser window and it should show a message
|
124
|
-
like:
|
125
|
-
</p>
|
126
|
-
<pre>
|
127
|
-
The current time is: Sun Jul 15 13:05:41 +0200 2007
|
128
|
-
</pre>
|
129
|
-
<p>
|
130
|
-
And the window title reads “Nuts And GORP”.
|
131
|
-
</p>
|
132
|
-
<p>
|
133
|
-
Here you can see we call <tt>render :sundial</tt> from our controller. This
|
134
|
-
does exactly what it says, and renders our <tt>sundial</tt> method.
|
135
|
-
We’ve also added a special method called <tt>layout</tt> which <a
|
136
|
-
href="../api.html#class-Camping">Camping</a> will automatically wrap our
|
137
|
-
sundial output in. If you’re familiar with HTML, you’ll see
|
138
|
-
that our view contains what looks HTML tag names. This is Markaby, which is
|
139
|
-
like writing HTML using Ruby!
|
140
|
-
</p>
|
141
|
-
<p>
|
142
|
-
Soon enough, you’ll find that you can return anything from the
|
143
|
-
controller, and it will be sent to the browser. But let’s keep that
|
144
|
-
for later and start investigating the routes.
|
145
|
-
</p>
|
146
|
-
<h2 class="ruled" id="routes">Routes</h2>
|
147
|
-
<p>
|
148
|
-
You probably noticed the weird <tt>R '/'</tt> syntax in the previous page.
|
149
|
-
This is an uncommon feature of Ruby that is used in our favorite
|
150
|
-
microframework, to describe the routes which the controller can be accessed
|
151
|
-
on.
|
152
|
-
</p>
|
153
|
-
<p>
|
154
|
-
These routes can be very powerful, but we’re going to have look at
|
155
|
-
the simplest ones first.
|
156
|
-
</p>
|
157
|
-
<pre>
|
158
|
-
module Nuts::Controllers
|
159
|
-
class Words < R '/welcome/to/my/site'
|
160
|
-
def get
|
161
|
-
"You got here by: /welcome/to/my/site"
|
162
|
-
end
|
163
|
-
end
|
164
|
-
|
165
|
-
class Digits < R '/nuts/(\d+)'
|
166
|
-
def get(number)
|
167
|
-
"You got here by: /nuts/#{number}"
|
168
|
-
end
|
169
|
-
end
|
170
|
-
|
171
|
-
class Segment < R '/gorp/([^/]+)'
|
172
|
-
def get(everything_else_than_a_slash)
|
173
|
-
"You got here by: /gorp/#{everything_else_than_a_slash}"
|
174
|
-
end
|
175
|
-
end
|
176
|
-
|
177
|
-
class DigitsAndEverything < R '/nuts/(\d+)/([^/]+)'
|
178
|
-
def get(number, everything)
|
179
|
-
"You got here by: /nuts/#{number}/#{everything}"
|
180
|
-
end
|
181
|
-
end
|
182
|
-
end
|
183
|
-
</pre>
|
184
|
-
<p>
|
185
|
-
Add this to nuts.rb and try if you can hit all of the controllers.
|
186
|
-
</p>
|
187
|
-
<p>
|
188
|
-
Also notice how everything inside a parenthesis gets passed into the
|
189
|
-
method, and is ready at your disposal.
|
190
|
-
</p>
|
191
|
-
<h3>Simpler routes</h3>
|
192
|
-
<p>
|
193
|
-
This just in:
|
194
|
-
</p>
|
195
|
-
<pre>
|
196
|
-
module Nuts::Controllers
|
197
|
-
class Index
|
198
|
-
def get
|
199
|
-
"You got here by: /"
|
200
|
-
end
|
201
|
-
end
|
202
|
-
|
203
|
-
class WelcomeToMySite
|
204
|
-
def get
|
205
|
-
"You got here by: /welcome/to/my/site"
|
206
|
-
end
|
207
|
-
end
|
208
|
-
|
209
|
-
class NutsN
|
210
|
-
def get(number)
|
211
|
-
"You got here by: /nuts/#{number}"
|
212
|
-
end
|
213
|
-
end
|
214
|
-
|
215
|
-
class GorpX
|
216
|
-
def get(everything_else_than_a_slash)
|
217
|
-
"You got here by: /gorp/#{everything_else_than_a_slash}"
|
218
|
-
end
|
219
|
-
end
|
220
|
-
|
221
|
-
class NutsNX
|
222
|
-
def get(number, everything)
|
223
|
-
"You got here by: /nuts/#{number}/#{everything}"
|
224
|
-
end
|
225
|
-
end
|
226
|
-
end
|
227
|
-
</pre>
|
228
|
-
<p>
|
229
|
-
Drop the <tt>< R</tt>-part and it attemps to read your mind. It
|
230
|
-
won’t always succeed, but it can simplify your application once in a
|
231
|
-
while.
|
232
|
-
</p>
|
233
|
-
<h2 class="ruled" id="modeling-the-world">Modeling the world</h2>
|
234
|
-
<p>
|
235
|
-
You can get pretty far with what you’ve learned now, and hopefully
|
236
|
-
you’ve been playing a bit off-book, but it’s time to take the
|
237
|
-
next step: Storing data.
|
238
|
-
</p>
|
239
|
-
<p>
|
240
|
-
Let’s start over again.
|
241
|
-
</p>
|
242
|
-
<pre>
|
243
|
-
Camping.goes :Nuts
|
244
|
-
|
245
|
-
module Nuts::Models
|
246
|
-
class Page < Base
|
247
|
-
end
|
248
|
-
end
|
249
|
-
</pre>
|
250
|
-
<p>
|
251
|
-
Obviously, this won’t do anything, since we don’t have any
|
252
|
-
controllers, but let’s rather have a look at we <em>do</em> have.
|
253
|
-
</p>
|
254
|
-
<p>
|
255
|
-
We have a model named Page. This means we now can store wiki pages and
|
256
|
-
retrieve them later. In fact, we can have as many models as we want. Need
|
257
|
-
one for your users and one for your blog posts? Well, I think you already
|
258
|
-
know how to do it.
|
259
|
-
</p>
|
260
|
-
<p>
|
261
|
-
However, our model is missing something essential: a skeleton.
|
262
|
-
</p>
|
263
|
-
<pre>
|
264
|
-
Camping.goes :Nuts
|
265
|
-
|
266
|
-
module Nuts::Models
|
267
|
-
class Page < Base
|
268
|
-
end
|
269
|
-
|
270
|
-
class BasicFields < V 1.0
|
271
|
-
def self.up
|
272
|
-
create_table Page.table_name do |t|
|
273
|
-
t.string :title
|
274
|
-
t.text :content
|
275
|
-
# This gives us created_at and updated_at
|
276
|
-
t.timestamps
|
277
|
-
end
|
278
|
-
end
|
279
|
-
|
280
|
-
def self.down
|
281
|
-
drop_table Page.table_name
|
282
|
-
end
|
283
|
-
end
|
284
|
-
end
|
285
|
-
</pre>
|
286
|
-
<p>
|
287
|
-
Now we have our first version of our model. It says:
|
288
|
-
</p>
|
289
|
-
<pre>
|
290
|
-
If you want to migrate up to version one,
|
291
|
-
create the skeleton for the Page model,
|
292
|
-
which should be able to store,
|
293
|
-
"title" which is a string,
|
294
|
-
"content" which is a larger text,
|
295
|
-
"created_at" which is the time it was created,
|
296
|
-
"updated_at" which is the previous time it was updated.
|
297
|
-
|
298
|
-
If you want to migrate down from version one,
|
299
|
-
remove the skeleton for the Page model.
|
300
|
-
</pre>
|
301
|
-
<p>
|
302
|
-
This is called a <em>migration</em>. Whenever you want to change or add new
|
303
|
-
models you simply add a new migration below, where you increase the version
|
304
|
-
number. All of these migrations builds upon each other like LEGO blocks.
|
305
|
-
</p>
|
306
|
-
<p>
|
307
|
-
Now we just need to tell <a href="../api.html#class-Camping">Camping</a> to
|
308
|
-
use our migration. Write this at the bottom of nuts.rb
|
309
|
-
</p>
|
310
|
-
<pre>
|
311
|
-
def Nuts.create
|
312
|
-
Nuts::Models.create_schema
|
313
|
-
end
|
314
|
-
</pre>
|
315
|
-
<p>
|
316
|
-
When The <a href="../api.html#class-Camping">Camping</a> Server boots up,
|
317
|
-
it will automatically call <tt>Nuts.create</tt>. You can put all kind of
|
318
|
-
startup-code here, but right now we only want to create our skeleton (or
|
319
|
-
upgrade if needed). Start The <a
|
320
|
-
href="../api.html#class-Camping">Camping</a> Server again and observe:
|
321
|
-
</p>
|
322
|
-
<pre>
|
323
|
-
$ camping nuts.rb
|
324
|
-
** Starting Mongrel on 0.0.0.0:3301
|
325
|
-
-- create_table("nuts_schema_infos")
|
326
|
-
-> 0.1035s
|
327
|
-
== Nuts::Models::BasicFields: migrating ===================================
|
328
|
-
-- create_table(:nuts_pages)
|
329
|
-
-> 0.0033s
|
330
|
-
== Nuts::Models::BasicFields: migrated (0.0038s) ==========================
|
331
|
-
</pre>
|
332
|
-
<p>
|
333
|
-
Restart it, and enjoy the silence. There’s no point of re-creating
|
334
|
-
the skeleton this time.
|
335
|
-
</p>
|
336
|
-
<p>
|
337
|
-
Before we go on, there’s one rule you must known: Always place your
|
338
|
-
models before your migrations.
|
339
|
-
</p>
|
340
|
-
<h2 class="ruled" id="using-our-model">Using our model</h2>
|
341
|
-
<p>
|
342
|
-
Let’s explore how our model works by going into the <em>console</em>
|
343
|
-
</p>
|
344
|
-
<pre>
|
345
|
-
$ camping -C nuts.rb
|
346
|
-
** Starting console
|
347
|
-
>>
|
348
|
-
</pre>
|
349
|
-
<p>
|
350
|
-
Now it’s waiting for your input, and will give you the answer when
|
351
|
-
you press Enter. Here’s what I did, leaving out the boring answers.
|
352
|
-
You should add your own pages.
|
353
|
-
</p>
|
354
|
-
<pre>
|
355
|
-
>> Page = Nuts::Models::Page
|
356
|
-
|
357
|
-
>> hiking = Page.new(:title => "Hiking")
|
358
|
-
>> hiking.content = "You can also set the values like this."
|
359
|
-
>> hiking.save
|
360
|
-
|
361
|
-
>> page = Page.find_by_title("Hiking")
|
362
|
-
=> #<Nuts::Models::Page id: 1, ... >
|
363
|
-
>> page = Page.find(1)
|
364
|
-
=> #<Nuts::Models::Page id: 1, ... >
|
365
|
-
>> page.title
|
366
|
-
>> page.content
|
367
|
-
>> page.created_at
|
368
|
-
>> page.updated_at
|
369
|
-
|
370
|
-
>> Page.find_by_title("Fishing")
|
371
|
-
=> nil
|
372
|
-
|
373
|
-
## Page.create automatically saves the page for you.
|
374
|
-
>> Page.create(:title => "Fishing", :content => "Go fish!")
|
375
|
-
|
376
|
-
>> Page.count
|
377
|
-
=> 2
|
378
|
-
</pre>
|
379
|
-
<p>
|
380
|
-
Now I have two pages: One about hiking and one about fishing.
|
381
|
-
</p>
|
382
|
-
<h2 class="ruled" id="wrapping-it-up">Wrapping it up</h2>
|
383
|
-
<p>
|
384
|
-
Wouldn’t it be nice if we could show this wonderful our pages in a
|
385
|
-
browser? Update nuts.rb so it also contains something like this:
|
386
|
-
</p>
|
387
|
-
<pre>
|
388
|
-
module Nuts::Controllers
|
389
|
-
class Pages
|
390
|
-
def get
|
391
|
-
# Only fetch the titles of the pages.
|
392
|
-
@pages = Page.all(:select => "title")
|
393
|
-
render :list
|
394
|
-
end
|
395
|
-
end
|
396
|
-
|
397
|
-
class PageX
|
398
|
-
def get(title)
|
399
|
-
@page = Page.find_by_title(title)
|
400
|
-
render :view
|
401
|
-
end
|
402
|
-
end
|
403
|
-
end
|
404
|
-
|
405
|
-
module Nuts::Views
|
406
|
-
def list
|
407
|
-
h1 "All pages"
|
408
|
-
ul do
|
409
|
-
@pages.each do |page|
|
410
|
-
li do
|
411
|
-
a page.title, :href => R(PageX, page.title)
|
412
|
-
end
|
413
|
-
end
|
414
|
-
end
|
415
|
-
end
|
416
|
-
|
417
|
-
def view
|
418
|
-
h1 @page.title
|
419
|
-
self << @page.content
|
420
|
-
end
|
421
|
-
end
|
422
|
-
</pre>
|
423
|
-
<p>
|
424
|
-
Here we meet our first <em>helper</em>:
|
425
|
-
</p>
|
426
|
-
<pre>
|
427
|
-
R(PageX, page.title)
|
428
|
-
</pre>
|
429
|
-
<p>
|
430
|
-
This is the <em>reversed router</em> and it generates a URL based on a
|
431
|
-
controller. <a href="../api.html#class-Camping">Camping</a> ships with a
|
432
|
-
few, but very useful, helpers and you can easily add your owns. Have a look
|
433
|
-
at <a href="../api.html#class-Camping-Helpers">Camping::Helpers</a> for how
|
434
|
-
you use these.
|
435
|
-
</p>
|
436
|
-
<p>
|
437
|
-
There’s a lot of improvements you could do here. Let me suggest:
|
438
|
-
</p>
|
439
|
-
<ul>
|
440
|
-
<li>Show when the page was created and last updated.
|
441
|
-
|
442
|
-
</li>
|
443
|
-
<li>What happens when the page doesn’t exist?
|
444
|
-
|
445
|
-
</li>
|
446
|
-
<li>What should the front page show?
|
447
|
-
|
448
|
-
</li>
|
449
|
-
<li>Add a layout.
|
450
|
-
|
451
|
-
</li>
|
452
|
-
<li>Jazz it up a bit.
|
453
|
-
|
454
|
-
</li>
|
455
|
-
</ul>
|
456
|
-
<h2 class="ruled" id="the-last-touch">The last touch</h2>
|
457
|
-
<p>
|
458
|
-
We have one major flaw in our little application. You can’t edit or
|
459
|
-
add new pages. Let’s see if we can fix that:
|
460
|
-
</p>
|
461
|
-
<pre>
|
462
|
-
module Nuts::Controllers
|
463
|
-
class PageX
|
464
|
-
def get(title)
|
465
|
-
if @page = Page.find_by_title(title)
|
466
|
-
render :view
|
467
|
-
else
|
468
|
-
redirect PageXEdit, title
|
469
|
-
end
|
470
|
-
end
|
471
|
-
|
472
|
-
def post(title)
|
473
|
-
# If it doesn't exist, initialize it:
|
474
|
-
@page = Page.find_or_initialize_by_title(title)
|
475
|
-
# This is the same as:
|
476
|
-
# @page = Page.find_by_title(title) || Page.new(:title => title)
|
477
|
-
|
478
|
-
@page.content = @input.content
|
479
|
-
@page.save
|
480
|
-
redirect PageX, title
|
481
|
-
end
|
482
|
-
end
|
483
|
-
|
484
|
-
class PageXEdit
|
485
|
-
def get(title)
|
486
|
-
@page = Page.find_or_initialize_by_title(title)
|
487
|
-
render :edit
|
488
|
-
end
|
489
|
-
end
|
490
|
-
end
|
491
|
-
</pre>
|
492
|
-
<p>
|
493
|
-
The core of this code lies in the new <tt>post</tt> method in the PageX
|
494
|
-
controller. When someone types an address or follows a link, they’ll
|
495
|
-
end up at the <tt>get</tt> method, but you can easily create a form which
|
496
|
-
rather sends you to the <tt>post</tt> when submitted.
|
497
|
-
</p>
|
498
|
-
<p>
|
499
|
-
There are other names you can use, but they won’t always work. So for
|
500
|
-
now, don’t be fancy and just stick to <tt>get</tt> and <tt>post</tt>.
|
501
|
-
We’ll show you how this really works later.
|
502
|
-
</p>
|
503
|
-
<p>
|
504
|
-
You might also notice that we use <tt>@input.content</tt>. The
|
505
|
-
<tt>@input</tt>-hash contains any extra parameters sent, like those in the
|
506
|
-
forms and those in the URL (<tt>/posts?page=50</tt>).
|
507
|
-
</p>
|
508
|
-
<p>
|
509
|
-
Here’s an <tt>edit</tt>-view, but you can probably do better. See if
|
510
|
-
you can integrate all of this with what you already have.
|
511
|
-
</p>
|
512
|
-
<pre>
|
513
|
-
module Nuts::Views
|
514
|
-
def edit
|
515
|
-
h1 @page.title
|
516
|
-
form :action => R(PageX, @page.title), :method => :post do
|
517
|
-
textarea @page.content, :name => :content,
|
518
|
-
:rows => 10, :cols => 50
|
519
|
-
|
520
|
-
br
|
521
|
-
|
522
|
-
input :type => :submit, :value => "Submit!"
|
523
|
-
end
|
524
|
-
end
|
525
|
-
end
|
526
|
-
</pre>
|
527
|
-
<h2 class="ruled" id="phew">Phew.</h2>
|
528
|
-
<p>
|
529
|
-
You’ve taken quite a few steps in the last minutes. You deserve a
|
530
|
-
break. But let’s recap for a moment:
|
531
|
-
</p>
|
532
|
-
<ul>
|
533
|
-
<li>Always place <tt><a href="../api.html#M000028">Camping.goes</a> :App</tt>
|
534
|
-
at the top of your file.
|
535
|
-
|
536
|
-
</li>
|
537
|
-
<li>Every route ends at a controller, but …
|
538
|
-
|
539
|
-
</li>
|
540
|
-
<li>… the controller only delegates the work.
|
541
|
-
|
542
|
-
</li>
|
543
|
-
<li><tt>@input</tt> contains the extra parameters.
|
544
|
-
|
545
|
-
</li>
|
546
|
-
<li>The views are HTML disguised as Ruby.
|
547
|
-
|
548
|
-
</li>
|
549
|
-
<li>They can access the instances variables (those that starts with a single
|
550
|
-
at-sign) from the controller.
|
551
|
-
|
552
|
-
</li>
|
553
|
-
<li>The models allows you to store all kinds of data.
|
554
|
-
|
555
|
-
</li>
|
556
|
-
<li>Place your models before your migrations.
|
557
|
-
|
558
|
-
</li>
|
559
|
-
<li>Helpers are helpful.
|
560
|
-
|
561
|
-
</li>
|
562
|
-
</ul>
|
563
|
-
<p>
|
564
|
-
Unfortunately, the book stops here for now. Come back in a few months, or
|
565
|
-
join the mailing list to stay updated, and hopefully there’s another
|
566
|
-
chapter waiting for you.
|
567
|
-
</p>
|
568
|
-
|
569
|
-
</div>
|
570
|
-
</div>
|
571
|
-
</div>
|
572
|
-
</body>
|
573
|
-
</html>
|