camping 2.0 → 2.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
- (&#8220;Eventually&#8221;, because these chapters are not written yet. This
37
- book is currently a very much work in progress, and we&#8217;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&#8217;re into that sort of things.
47
- </p>
48
- <p>
49
- Enough talk. Ready? Let&#8217;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&#8217;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&#8217;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&#8217;t know what to show. Let&#8217;s tell
62
- him.
63
- </p>
64
- <h2 class="ruled" id="hello-clock">Hello clock</h2>
65
- <p>
66
- So, you&#8217;ve got <a href="../api.html#class-Camping">Camping</a>
67
- installed and it&#8217;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&#8217;s show something. At the bottom of nuts.rb add:
73
- </p>
74
- <pre>
75
- module Nuts::Controllers
76
- class Index &lt; 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&#8217;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 &lt; 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 { &quot;Nuts And GORP&quot; }
112
- end
113
- body { self &lt;&lt; yield }
114
- end
115
- end
116
-
117
- def sundial
118
- p &quot;The current time is: #{@time}&quot;
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 &#8220;Nuts And GORP&#8221;.
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&#8217;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&#8217;re familiar with HTML, you&#8217;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&#8217;ll find that you can return anything from the
143
- controller, and it will be sent to the browser. But let&#8217;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&#8217;re going to have look at
155
- the simplest ones first.
156
- </p>
157
- <pre>
158
- module Nuts::Controllers
159
- class Words &lt; R '/welcome/to/my/site'
160
- def get
161
- &quot;You got here by: /welcome/to/my/site&quot;
162
- end
163
- end
164
-
165
- class Digits &lt; R '/nuts/(\d+)'
166
- def get(number)
167
- &quot;You got here by: /nuts/#{number}&quot;
168
- end
169
- end
170
-
171
- class Segment &lt; R '/gorp/([^/]+)'
172
- def get(everything_else_than_a_slash)
173
- &quot;You got here by: /gorp/#{everything_else_than_a_slash}&quot;
174
- end
175
- end
176
-
177
- class DigitsAndEverything &lt; R '/nuts/(\d+)/([^/]+)'
178
- def get(number, everything)
179
- &quot;You got here by: /nuts/#{number}/#{everything}&quot;
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
- &quot;You got here by: /&quot;
200
- end
201
- end
202
-
203
- class WelcomeToMySite
204
- def get
205
- &quot;You got here by: /welcome/to/my/site&quot;
206
- end
207
- end
208
-
209
- class NutsN
210
- def get(number)
211
- &quot;You got here by: /nuts/#{number}&quot;
212
- end
213
- end
214
-
215
- class GorpX
216
- def get(everything_else_than_a_slash)
217
- &quot;You got here by: /gorp/#{everything_else_than_a_slash}&quot;
218
- end
219
- end
220
-
221
- class NutsNX
222
- def get(number, everything)
223
- &quot;You got here by: /nuts/#{number}/#{everything}&quot;
224
- end
225
- end
226
- end
227
- </pre>
228
- <p>
229
- Drop the <tt>&lt; R</tt>-part and it attemps to read your mind. It
230
- won&#8217;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&#8217;ve learned now, and hopefully
236
- you&#8217;ve been playing a bit off-book, but it&#8217;s time to take the
237
- next step: Storing data.
238
- </p>
239
- <p>
240
- Let&#8217;s start over again.
241
- </p>
242
- <pre>
243
- Camping.goes :Nuts
244
-
245
- module Nuts::Models
246
- class Page &lt; Base
247
- end
248
- end
249
- </pre>
250
- <p>
251
- Obviously, this won&#8217;t do anything, since we don&#8217;t have any
252
- controllers, but let&#8217;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 &lt; Base
268
- end
269
-
270
- class BasicFields &lt; 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
- &quot;title&quot; which is a string,
294
- &quot;content&quot; which is a larger text,
295
- &quot;created_at&quot; which is the time it was created,
296
- &quot;updated_at&quot; 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(&quot;nuts_schema_infos&quot;)
326
- -&gt; 0.1035s
327
- == Nuts::Models::BasicFields: migrating ===================================
328
- -- create_table(:nuts_pages)
329
- -&gt; 0.0033s
330
- == Nuts::Models::BasicFields: migrated (0.0038s) ==========================
331
- </pre>
332
- <p>
333
- Restart it, and enjoy the silence. There&#8217;s no point of re-creating
334
- the skeleton this time.
335
- </p>
336
- <p>
337
- Before we go on, there&#8217;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&#8217;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
- &gt;&gt;
348
- </pre>
349
- <p>
350
- Now it&#8217;s waiting for your input, and will give you the answer when
351
- you press Enter. Here&#8217;s what I did, leaving out the boring answers.
352
- You should add your own pages.
353
- </p>
354
- <pre>
355
- &gt;&gt; Page = Nuts::Models::Page
356
-
357
- &gt;&gt; hiking = Page.new(:title =&gt; &quot;Hiking&quot;)
358
- &gt;&gt; hiking.content = &quot;You can also set the values like this.&quot;
359
- &gt;&gt; hiking.save
360
-
361
- &gt;&gt; page = Page.find_by_title(&quot;Hiking&quot;)
362
- =&gt; #&lt;Nuts::Models::Page id: 1, ... &gt;
363
- &gt;&gt; page = Page.find(1)
364
- =&gt; #&lt;Nuts::Models::Page id: 1, ... &gt;
365
- &gt;&gt; page.title
366
- &gt;&gt; page.content
367
- &gt;&gt; page.created_at
368
- &gt;&gt; page.updated_at
369
-
370
- &gt;&gt; Page.find_by_title(&quot;Fishing&quot;)
371
- =&gt; nil
372
-
373
- ## Page.create automatically saves the page for you.
374
- &gt;&gt; Page.create(:title =&gt; &quot;Fishing&quot;, :content =&gt; &quot;Go fish!&quot;)
375
-
376
- &gt;&gt; Page.count
377
- =&gt; 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&#8217;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 =&gt; &quot;title&quot;)
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 &quot;All pages&quot;
408
- ul do
409
- @pages.each do |page|
410
- li do
411
- a page.title, :href =&gt; R(PageX, page.title)
412
- end
413
- end
414
- end
415
- end
416
-
417
- def view
418
- h1 @page.title
419
- self &lt;&lt; @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&#8217;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&#8217;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&#8217;t edit or
459
- add new pages. Let&#8217;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 =&gt; 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&#8217;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&#8217;t always work. So for
500
- now, don&#8217;t be fancy and just stick to <tt>get</tt> and <tt>post</tt>.
501
- We&#8217;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&#8217;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 =&gt; R(PageX, @page.title), :method =&gt; :post do
517
- textarea @page.content, :name =&gt; :content,
518
- :rows =&gt; 10, :cols =&gt; 50
519
-
520
- br
521
-
522
- input :type =&gt; :submit, :value =&gt; &quot;Submit!&quot;
523
- end
524
- end
525
- end
526
- </pre>
527
- <h2 class="ruled" id="phew">Phew.</h2>
528
- <p>
529
- You&#8217;ve taken quite a few steps in the last minutes. You deserve a
530
- break. But let&#8217;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 &#8230;
538
-
539
- </li>
540
- <li>&#8230; 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&#8217;s another
566
- chapter waiting for you.
567
- </p>
568
-
569
- </div>
570
- </div>
571
- </div>
572
- </body>
573
- </html>