camping 2.0 → 2.1

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