camping 1.5.180 → 2.0.rc0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. data/CHANGELOG +35 -0
  2. data/README +43 -68
  3. data/Rakefile +155 -86
  4. data/bin/camping +64 -246
  5. data/book/01_introduction +19 -0
  6. data/book/02_getting_started +443 -0
  7. data/book/51_upgrading +93 -0
  8. data/doc/api.html +1953 -0
  9. data/doc/book.html +73 -0
  10. data/doc/book/01_introduction.html +57 -0
  11. data/doc/book/02_getting_started.html +573 -0
  12. data/doc/book/51_upgrading.html +146 -0
  13. data/doc/created.rid +1 -0
  14. data/{extras → doc/images}/Camping.gif +0 -0
  15. data/doc/images/loadingAnimation.gif +0 -0
  16. data/{extras → doc/images}/permalink.gif +0 -0
  17. data/doc/index.html +148 -0
  18. data/doc/js/camping.js +79 -0
  19. data/doc/js/jquery.js +32 -0
  20. data/doc/rdoc.css +117 -0
  21. data/examples/blog.rb +280 -181
  22. data/extras/images/badge.gif +0 -0
  23. data/extras/images/boys-life.png +0 -0
  24. data/extras/images/deerputer.png +0 -0
  25. data/extras/images/diagram.png +0 -0
  26. data/extras/images/hill.png +0 -0
  27. data/extras/images/i-wish.png +0 -0
  28. data/extras/images/latl.png +0 -0
  29. data/extras/images/little-wheels.png +0 -0
  30. data/extras/images/square-badge.png +0 -0
  31. data/extras/images/uniform.png +0 -0
  32. data/extras/images/whale-bounce.png +0 -0
  33. data/extras/rdoc/generator/singledarkfish.rb +205 -0
  34. data/extras/rdoc/generator/template/flipbook/images/Camping.gif +0 -0
  35. data/extras/rdoc/generator/template/flipbook/images/loadingAnimation.gif +0 -0
  36. data/extras/rdoc/generator/template/flipbook/images/permalink.gif +0 -0
  37. data/extras/rdoc/generator/template/flipbook/js/camping.js +79 -0
  38. data/extras/rdoc/generator/template/flipbook/js/jquery.js +32 -0
  39. data/extras/rdoc/generator/template/flipbook/page.rhtml +30 -0
  40. data/extras/rdoc/generator/template/flipbook/rdoc.css +117 -0
  41. data/extras/rdoc/generator/template/flipbook/readme.rhtml +31 -0
  42. data/extras/rdoc/generator/template/flipbook/reference.rhtml +71 -0
  43. data/extras/rdoc/generator/template/flipbook/toc.rhtml +43 -0
  44. data/lib/camping-unabridged.rb +420 -481
  45. data/lib/camping.rb +40 -55
  46. data/lib/camping/{db.rb → ar.rb} +5 -8
  47. data/lib/camping/mab.rb +26 -0
  48. data/lib/camping/reloader.rb +175 -147
  49. data/lib/camping/server.rb +178 -0
  50. data/lib/camping/session.rb +34 -121
  51. data/test/apps/env_debug.rb +65 -0
  52. data/test/apps/forms.rb +95 -0
  53. data/test/apps/forward_to_other_controller.rb +60 -0
  54. data/test/apps/migrations.rb +97 -0
  55. data/test/apps/misc.rb +86 -0
  56. data/test/apps/sessions.rb +38 -0
  57. metadata +120 -80
  58. data/doc/camping.1.gz +0 -0
  59. data/examples/campsh.rb +0 -630
  60. data/examples/tepee.rb +0 -242
  61. data/extras/flipbook_rdoc.rb +0 -491
  62. data/lib/camping/fastcgi.rb +0 -244
  63. data/lib/camping/webrick.rb +0 -65
  64. data/test/test_xhtml_trans.rb +0 -55
data/book/51_upgrading ADDED
@@ -0,0 +1,93 @@
1
+ = Appendix I: Upgrade Notes
2
+
3
+ == From 1.5 to 2.0
4
+ === Rack
5
+
6
+ The biggest change in 2.0 is that it now uses Rack[http://rack.rubyforge.org/]
7
+ internally. This means that you'll now have to deploy Camping differently, but
8
+ hopefully more easily too. Now every Camping application is also a Rack
9
+ application, so simply check out the documentation to the server of your
10
+ choice.
11
+
12
+ === require 'camping/db'
13
+
14
+ In earlier versions of Camping, you loaded database support by:
15
+
16
+ require 'camping/db'
17
+
18
+ Actually, this loaded a very thin layer on top of ActiveRecord, and in the
19
+ future we want to experiment with other libraries. Therefore you should now
20
+ simply remove the line, and instead just inherit from Base right away. This
21
+ also means you'll have to place your migrations *after* the models.
22
+
23
+ We also encourage you to use <tt>Model.table_name</tt> instead of
24
+ <tt>:appname_model</tt>, just to make sure it's named correctly.
25
+
26
+ ## Don't require anything:
27
+ # require 'camping/db'
28
+
29
+ module Nuts::Models
30
+ ## Just inherit Base:
31
+ class Page < Base; end
32
+
33
+ ## Migrations have to come *after* the models:
34
+ class CreateTheBasics < V 0.1
35
+ def self.up
36
+ create_table Page.table_name do |t|
37
+ ...
38
+ end
39
+ end
40
+
41
+ def self.down
42
+ drop_table Page.table_name
43
+ end
44
+ end
45
+ end
46
+
47
+ === Cookie Sessions
48
+
49
+ Camping 2.0 now uses a cookie-based session system, which means you now longer
50
+ need a database in order to use sessions. The disadvantage of this is that
51
+ you are restricted to only around 4k of data. See below for the changes
52
+ required, and see Camping::Session more details.
53
+
54
+ module Nuts
55
+ ## Include Camping::Session as before:
56
+ include Camping::Session
57
+
58
+ ## But also define a secret:
59
+ secret "Very secret text, which no-one else should know!"
60
+ end
61
+
62
+ def Nuts.create
63
+ ## And remove the following line:
64
+ # Camping::Models::Session.create_schema
65
+ end
66
+
67
+ === Error handling
68
+
69
+ Camping now uses three methods in order to handle errors. These replaces the
70
+ old classes NotFound and ServerError.
71
+
72
+ * Camping::Base#r404 is called when a route can't be found.
73
+ * Camping::Base#r501 is called when a route is found, but doesn't respond to
74
+ the method.
75
+ * Camping::Base#r500 is called when an error happens.
76
+
77
+ You can override these in your application:
78
+
79
+ module Nuts
80
+ def r404(path)
81
+ "Sorry, but I can't find #{path}."
82
+ end
83
+
84
+ def r501(method)
85
+ "Sorry, but I can't respond to #{method}."
86
+ end
87
+
88
+ def r500(klass, method, ex)
89
+ "Sorry, but #{klass}##{method} failed with #{ex}."
90
+ end
91
+ end
92
+
93
+ It should be noted that this might change in the future.
data/doc/api.html ADDED
@@ -0,0 +1,1953 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Camping, the Reference</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">book</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.rc0</p>
18
+ </div>
19
+
20
+ <div id="fullpage">
21
+ <div class="page_shade">
22
+ <div class="page ref">
23
+ <p class="header">Sat Apr 03 16:22:17 +0200 2010</p>
24
+ <h1>Camping, the Reference</h1>
25
+
26
+
27
+ <h2 id="class-Camping">
28
+ <a href="#class-Camping">
29
+ Module
30
+ Camping
31
+
32
+ </a>
33
+ </h2>
34
+
35
+ <div class="mod">
36
+ <p>
37
+ If you&#8217;re new to <a href="api.html#class-Camping">Camping</a>, you
38
+ should probably start by reading the first chapters of <a
39
+ href="file:book/01_introduction.html#toc">The Camping Book</a>.
40
+ </p>
41
+ <p>
42
+ Okay. So, the important thing to remember is that <tt><a
43
+ href="api.html#M000023">Camping.goes</a> :Nuts</tt> copies the <a
44
+ href="api.html#class-Camping">Camping</a> module into Nuts. This means that
45
+ you should never use any of these methods/classes on the <a
46
+ href="api.html#class-Camping">Camping</a> module, but rather on your own
47
+ app. Here&#8217;s a short explanation on how <a
48
+ href="api.html#class-Camping">Camping</a> is organized:
49
+ </p>
50
+ <ul>
51
+ <li><a href="api.html#class-Camping-Controllers">Camping::Controllers</a> is
52
+ where your controllers live.
53
+
54
+ </li>
55
+ <li><a href="api.html#class-Camping-Models">Camping::Models</a> is where your
56
+ models live.
57
+
58
+ </li>
59
+ <li><a href="api.html#class-Camping-Views">Camping::Views</a> is where your
60
+ views live.
61
+
62
+ </li>
63
+ <li><a href="api.html#class-Camping-Base">Camping::Base</a> is a module which
64
+ is included in all your controllers.
65
+
66
+ </li>
67
+ <li><a href="api.html#class-Camping-Helpers">Camping::Helpers</a> is a module
68
+ with useful helpers, both for the controllers and the views. You should
69
+ fill this up with your own helpers.
70
+
71
+ </li>
72
+ </ul>
73
+ <p>
74
+ <a href="api.html#class-Camping">Camping</a> also ships with:
75
+ </p>
76
+ <ul>
77
+ <li><a href="api.html#class-Camping-Session">Camping::Session</a> adds states
78
+ to your app.
79
+
80
+ </li>
81
+ <li><a href="api.html#class-Camping-Server">Camping::Server</a> starts up your
82
+ app in development.
83
+
84
+ </li>
85
+ <li><a href="api.html#class-Camping-Reloader">Camping::Reloader</a>
86
+ automatically reloads your apps when a file has changed.
87
+
88
+ </li>
89
+ </ul>
90
+ <p>
91
+ More importantly, <a href="api.html#class-Camping">Camping</a> also
92
+ installs The <a href="api.html#class-Camping">Camping</a> <a
93
+ href="api.html#class-Camping-Server">Server</a>, please see <a
94
+ href="api.html#class-Camping-Server">Camping::Server</a>.
95
+ </p>
96
+
97
+
98
+ <h3>Methods</h3>
99
+
100
+ <h4 class="ruled" id="M000024">
101
+ <a href="#M000024">
102
+ Public Class method:
103
+ <strong>::call(e)</strong>
104
+ <img src="./images/permalink.gif">
105
+ </a>
106
+ </h4>
107
+ <div class="method">
108
+ <p>
109
+ Ruby web servers use this method to enter the <a
110
+ href="api.html#class-Camping">Camping</a> realm. The <tt>e</tt> argument is
111
+ the environment variables hash as per the Rack specification. And array
112
+ with [status, headers, body] is expected at the output.
113
+ </p>
114
+ <p>
115
+ See: <a
116
+ href="http://rack.rubyforge.org/doc/SPEC.html">rack.rubyforge.org/doc/SPEC.html</a>
117
+ </p>
118
+
119
+ <p class="source-link">[ <a href="#">show source</a> ]</p>
120
+ <pre class="sourcecode">
121
+ <span class="ruby-comment cmt"># File lib/camping-unabridged.rb, line 584</span>
122
+ 584: <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">call</span>(<span class="ruby-identifier">e</span>)
123
+ 585: <span class="ruby-constant">X</span>.<span class="ruby-constant">M</span>
124
+ 586: <span class="ruby-identifier">p</span> = <span class="ruby-identifier">e</span>[<span class="ruby-value str">'PATH_INFO'</span>] = <span class="ruby-constant">U</span>.<span class="ruby-identifier">unescape</span>(<span class="ruby-identifier">e</span>[<span class="ruby-value str">'PATH_INFO'</span>])
125
+ 587: <span class="ruby-identifier">k</span>,<span class="ruby-identifier">m</span>,<span class="ruby-operator">*</span><span class="ruby-identifier">a</span>=<span class="ruby-constant">X</span>.<span class="ruby-constant">D</span> <span class="ruby-identifier">p</span>,<span class="ruby-identifier">e</span>[<span class="ruby-value str">'REQUEST_METHOD'</span>].<span class="ruby-identifier">downcase</span>
126
+ 588: <span class="ruby-identifier">k</span>.<span class="ruby-identifier">new</span>(<span class="ruby-identifier">e</span>,<span class="ruby-identifier">m</span>).<span class="ruby-identifier">service</span>(<span class="ruby-operator">*</span><span class="ruby-identifier">a</span>).<span class="ruby-identifier">to_a</span>
127
+ 589: <span class="ruby-keyword kw">rescue</span>
128
+ 590: <span class="ruby-identifier">r500</span>(<span class="ruby-identifier">:I</span>, <span class="ruby-identifier">k</span>, <span class="ruby-identifier">m</span>, <span class="ruby-identifier">$!</span>, <span class="ruby-identifier">:env</span> =<span class="ruby-operator">&gt;</span> <span class="ruby-identifier">e</span>).<span class="ruby-identifier">to_a</span>
129
+ 591: <span class="ruby-keyword kw">end</span></pre>
130
+ </div>
131
+
132
+ <h4 class="ruled" id="M000023">
133
+ <a href="#M000023">
134
+ Public Class method:
135
+ <strong>::goes(m)</strong>
136
+ <img src="./images/permalink.gif">
137
+ </a>
138
+ </h4>
139
+ <div class="method">
140
+ <p>
141
+ When you are running many applications, you may want to create independent
142
+ modules for each <a href="api.html#class-Camping">Camping</a> application.
143
+ Camping::goes defines a toplevel constant with the whole MVC rack inside:
144
+ </p>
145
+ <pre>
146
+ require 'camping'
147
+ Camping.goes :Nuts
148
+
149
+ module Nuts::Controllers; ... end
150
+ module Nuts::Models; ... end
151
+ module Nuts::Views; ... end
152
+ </pre>
153
+ <p>
154
+ All the applications will be available in Camping::Apps.
155
+ </p>
156
+
157
+ <p class="source-link">[ <a href="#">show source</a> ]</p>
158
+ <pre class="sourcecode">
159
+ <span class="ruby-comment cmt"># File lib/camping-unabridged.rb, line 575</span>
160
+ 575: <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">goes</span>(<span class="ruby-identifier">m</span>)
161
+ 576: <span class="ruby-constant">Apps</span> <span class="ruby-operator">&lt;&lt;</span> <span class="ruby-identifier">eval</span>(<span class="ruby-constant">S</span>.<span class="ruby-identifier">gsub</span>(<span class="ruby-regexp re">/Camping/</span>,<span class="ruby-identifier">m</span>.<span class="ruby-identifier">to_s</span>), <span class="ruby-constant">TOPLEVEL_BINDING</span>)
162
+ 577: <span class="ruby-keyword kw">end</span></pre>
163
+ </div>
164
+
165
+ <h4 class="ruled" id="M000027">
166
+ <a href="#M000027">
167
+ Public Class method:
168
+ <strong>::method_missing(m, c, *a)</strong>
169
+ <img src="./images/permalink.gif">
170
+ </a>
171
+ </h4>
172
+ <div class="method">
173
+ <p>
174
+ The <a href="api.html#class-Camping">Camping</a> scriptable dispatcher. Any
175
+ unhandled method call to the app module will be sent to a controller class,
176
+ specified as an argument.
177
+ </p>
178
+ <pre>
179
+ Blog.get(:Index)
180
+ #=&gt; #&lt;Blog::Controllers::Index ... &gt;
181
+ </pre>
182
+ <p>
183
+ The controller object contains all the @cookies, @body, @headers, etc.
184
+ formulated by the response.
185
+ </p>
186
+ <p>
187
+ You can also feed environment variables and query variables as a hash, the
188
+ final argument.
189
+ </p>
190
+ <pre>
191
+ Blog.post(:Login, :input =&gt; {'username' =&gt; 'admin', 'password' =&gt; 'camping'})
192
+ #=&gt; #&lt;Blog::Controllers::Login @user=... &gt;
193
+
194
+ Blog.get(:Info, :env =&gt; {'HTTP_HOST' =&gt; 'wagon'})
195
+ #=&gt; #&lt;Blog::Controllers::Info @headers={'HTTP_HOST'=&gt;'wagon'} ...&gt;
196
+ </pre>
197
+
198
+ <p class="source-link">[ <a href="#">show source</a> ]</p>
199
+ <pre class="sourcecode">
200
+ <span class="ruby-comment cmt"># File lib/camping-unabridged.rb, line 611</span>
201
+ 611: <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">method_missing</span>(<span class="ruby-identifier">m</span>, <span class="ruby-identifier">c</span>, <span class="ruby-operator">*</span><span class="ruby-identifier">a</span>)
202
+ 612: <span class="ruby-constant">X</span>.<span class="ruby-constant">M</span>
203
+ 613: <span class="ruby-identifier">h</span> = <span class="ruby-constant">Hash</span> <span class="ruby-operator">===</span> <span class="ruby-identifier">a</span>[<span class="ruby-value">-1</span>] <span class="ruby-operator">?</span> <span class="ruby-identifier">a</span>.<span class="ruby-identifier">pop</span> <span class="ruby-operator">:</span> {}
204
+ 614: <span class="ruby-identifier">e</span> = <span class="ruby-constant">H</span>[<span class="ruby-constant">Rack</span><span class="ruby-operator">::</span><span class="ruby-constant">MockRequest</span>.<span class="ruby-identifier">env_for</span>(<span class="ruby-value str">''</span>,<span class="ruby-identifier">h</span>.<span class="ruby-identifier">delete</span>(<span class="ruby-identifier">:env</span>)<span class="ruby-operator">||</span>{})]
205
+ 615: <span class="ruby-identifier">k</span> = <span class="ruby-constant">X</span>.<span class="ruby-identifier">const_get</span>(<span class="ruby-identifier">c</span>).<span class="ruby-identifier">new</span>(<span class="ruby-identifier">e</span>,<span class="ruby-identifier">m</span>.<span class="ruby-identifier">to_s</span>)
206
+ 616: <span class="ruby-identifier">h</span>.<span class="ruby-identifier">each</span> { <span class="ruby-operator">|</span><span class="ruby-identifier">i</span>, <span class="ruby-identifier">v</span><span class="ruby-operator">|</span> <span class="ruby-identifier">k</span>.<span class="ruby-identifier">send</span>(<span class="ruby-node">&quot;#{i}=&quot;</span>, <span class="ruby-identifier">v</span>) }
207
+ 617: <span class="ruby-identifier">k</span>.<span class="ruby-identifier">service</span>(<span class="ruby-operator">*</span><span class="ruby-identifier">a</span>)
208
+ 618: <span class="ruby-keyword kw">end</span></pre>
209
+ </div>
210
+
211
+ <h4 class="ruled" id="M000031">
212
+ <a href="#M000031">
213
+ Public Class method:
214
+ <strong>::use(*a, &b)</strong>
215
+ <img src="./images/permalink.gif">
216
+ </a>
217
+ </h4>
218
+ <div class="method">
219
+ <p>
220
+ Injects a middleware:
221
+ </p>
222
+ <pre>
223
+ module Blog
224
+ use Rack::MethodOverride
225
+ use Rack::Session::Memcache, :key =&gt; &quot;session&quot;
226
+ end
227
+ </pre>
228
+
229
+ <p class="source-link">[ <a href="#">show source</a> ]</p>
230
+ <pre class="sourcecode">
231
+ <span class="ruby-comment cmt"># File lib/camping-unabridged.rb, line 626</span>
232
+ 626: <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">use</span>(<span class="ruby-operator">*</span><span class="ruby-identifier">a</span>, <span class="ruby-operator">&amp;</span><span class="ruby-identifier">b</span>)
233
+ 627: <span class="ruby-identifier">m</span> = <span class="ruby-identifier">a</span>.<span class="ruby-identifier">shift</span>.<span class="ruby-identifier">new</span>(<span class="ruby-identifier">method</span>(<span class="ruby-identifier">:call</span>), <span class="ruby-operator">*</span><span class="ruby-identifier">a</span>, <span class="ruby-operator">&amp;</span><span class="ruby-identifier">b</span>)
234
+ 628: <span class="ruby-identifier">meta_def</span>(<span class="ruby-identifier">:call</span>) { <span class="ruby-operator">|</span><span class="ruby-identifier">e</span><span class="ruby-operator">|</span> <span class="ruby-identifier">m</span>.<span class="ruby-identifier">call</span>(<span class="ruby-identifier">e</span>) }
235
+ 629: <span class="ruby-keyword kw">end</span></pre>
236
+ </div>
237
+
238
+ </div>
239
+
240
+ <h2 id="class-Camping-Base">
241
+ <a href="#class-Camping-Base">
242
+ Module
243
+ Camping::Base
244
+
245
+ </a>
246
+ </h2>
247
+
248
+ <div class="mod">
249
+ <p>
250
+ <a href="api.html#class-Camping-Base">Camping::Base</a> is built into each
251
+ controller by way of the generic routing class Camping::R. In some ways,
252
+ this class is trying to do too much, but it saves code for all the glue to
253
+ stay in one place. Forgivable, considering that it&#8217;s only really a
254
+ handful of methods and accessors.
255
+ </p>
256
+ <p>
257
+ Everything in this module is accessable inside your controllers.
258
+ </p>
259
+
260
+
261
+ <h3>Methods</h3>
262
+
263
+ <h4 class="ruled" id="M000006">
264
+ <a href="#M000006">
265
+ Public Instance method:
266
+ <strong>#mab(l=nil,&b)</strong>
267
+ <img src="./images/permalink.gif">
268
+ </a>
269
+ </h4>
270
+ <div class="method">
271
+ <p>
272
+ You can directly return HTML form your controller for quick debugging by
273
+ calling this method and pass some Markaby to it.
274
+ </p>
275
+ <pre>
276
+ module Nuts::Controllers
277
+ class Info
278
+ def get; mab{ code @headers.inspect } end
279
+ end
280
+ end
281
+ </pre>
282
+ <p>
283
+ You can also pass true to use the :layout HTML wrapping method
284
+ </p>
285
+
286
+ <p class="source-link">[ <a href="#">show source</a> ]</p>
287
+ <pre class="sourcecode">
288
+ <span class="ruby-comment cmt"># File lib/camping-unabridged.rb, line 265</span>
289
+ 265: <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">mab</span>(<span class="ruby-identifier">l</span>=<span class="ruby-keyword kw">nil</span>,<span class="ruby-operator">&amp;</span><span class="ruby-identifier">b</span>)
290
+ 266: <span class="ruby-identifier">m</span>=<span class="ruby-constant">Mab</span>.<span class="ruby-identifier">new</span>({},<span class="ruby-keyword kw">self</span>)
291
+ 267: <span class="ruby-identifier">s</span>=<span class="ruby-identifier">m</span>.<span class="ruby-identifier">capture</span>(<span class="ruby-operator">&amp;</span><span class="ruby-identifier">b</span>)
292
+ 268: <span class="ruby-identifier">s</span>=<span class="ruby-identifier">m</span>.<span class="ruby-identifier">capture</span>{<span class="ruby-identifier">layout</span>{<span class="ruby-identifier">s</span>}} <span class="ruby-keyword kw">if</span> <span class="ruby-identifier">l</span> <span class="ruby-operator">&amp;&amp;</span> <span class="ruby-identifier">m</span>.<span class="ruby-identifier">respond_to?</span>(<span class="ruby-identifier">:layout</span>)
293
+ 269: <span class="ruby-identifier">s</span>
294
+ 270: <span class="ruby-keyword kw">end</span></pre>
295
+ </div>
296
+
297
+ <h4 class="ruled" id="M000007">
298
+ <a href="#M000007">
299
+ Public Instance method:
300
+ <strong>#r(s, b, h = {})</strong>
301
+ <img src="./images/permalink.gif">
302
+ </a>
303
+ </h4>
304
+ <div class="method">
305
+ <p>
306
+ A quick means of setting this controller&#8217;s status, body and headers
307
+ based on a Rack response:
308
+ </p>
309
+ <pre>
310
+ r(302, 'Location' =&gt; self / &quot;/view/12&quot;, '')
311
+ r(*another_app.call(@env))
312
+ </pre>
313
+ <p>
314
+ You can also switch the body and the header if you want:
315
+ </p>
316
+ <pre>
317
+ r(404, &quot;Could not find page&quot;)
318
+ </pre>
319
+ <p>
320
+ See also: <a href="api.html#M000009">r404</a>, <a
321
+ href="api.html#M000010">r500</a> and <a href="api.html#M000011">r501</a>
322
+ </p>
323
+
324
+ <p class="source-link">[ <a href="#">show source</a> ]</p>
325
+ <pre class="sourcecode">
326
+ <span class="ruby-comment cmt"># File lib/camping-unabridged.rb, line 283</span>
327
+ 283: <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">r</span>(<span class="ruby-identifier">s</span>, <span class="ruby-identifier">b</span>, <span class="ruby-identifier">h</span> = {})
328
+ 284: <span class="ruby-identifier">b</span>, <span class="ruby-identifier">h</span> = <span class="ruby-identifier">h</span>, <span class="ruby-identifier">b</span> <span class="ruby-keyword kw">if</span> <span class="ruby-constant">Hash</span> <span class="ruby-operator">===</span> <span class="ruby-identifier">b</span>
329
+ 285: <span class="ruby-ivar">@status</span> = <span class="ruby-identifier">s</span>
330
+ 286: <span class="ruby-ivar">@headers</span>.<span class="ruby-identifier">merge!</span>(<span class="ruby-identifier">h</span>)
331
+ 287: <span class="ruby-ivar">@body</span> = <span class="ruby-identifier">b</span>
332
+ 288: <span class="ruby-keyword kw">end</span></pre>
333
+ </div>
334
+
335
+ <h4 class="ruled" id="M000009">
336
+ <a href="#M000009">
337
+ Public Instance method:
338
+ <strong>#r404(p)</strong>
339
+ <img src="./images/permalink.gif">
340
+ </a>
341
+ </h4>
342
+ <div class="method">
343
+ <p>
344
+ Called when a controller was not found. You can override this if you want
345
+ to customize the error page:
346
+ </p>
347
+ <pre>
348
+ module Nuts
349
+ def r404(path)
350
+ @path = path
351
+ render :not_found
352
+ end
353
+ end
354
+ </pre>
355
+
356
+ <p class="source-link">[ <a href="#">show source</a> ]</p>
357
+ <pre class="sourcecode">
358
+ <span class="ruby-comment cmt"># File lib/camping-unabridged.rb, line 317</span>
359
+ 317: <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">r404</span>(<span class="ruby-identifier">p</span>)
360
+ 318: <span class="ruby-constant">P</span> <span class="ruby-operator">%</span> <span class="ruby-node">&quot;#{p} not found&quot;</span>
361
+ 319: <span class="ruby-keyword kw">end</span></pre>
362
+ </div>
363
+
364
+ <h4 class="ruled" id="M000010">
365
+ <a href="#M000010">
366
+ Public Instance method:
367
+ <strong>#r500(k,m,e)</strong>
368
+ <img src="./images/permalink.gif">
369
+ </a>
370
+ </h4>
371
+ <div class="method">
372
+ <p>
373
+ Called when an exception is raised. However, if there is a parse error in
374
+ <a href="api.html#class-Camping">Camping</a> or in your application&#8217;s
375
+ source code, it will not be caught.
376
+ </p>
377
+ <p>
378
+ <tt>k</tt> is the controller class, <tt>m</tt> is the request method (GET,
379
+ POST, etc.) and <tt>e</tt> is the Exception which can be mined for useful
380
+ info.
381
+ </p>
382
+ <p>
383
+ Be default this simply re-raises the error so a Rack middleware can handle
384
+ it, but you are free to override it here:
385
+ </p>
386
+ <pre>
387
+ module Nuts
388
+ def r500(klass, method, exception)
389
+ send_email_alert(klass, method, exception)
390
+ render :server_error
391
+ end
392
+ end
393
+ </pre>
394
+
395
+ <p class="source-link">[ <a href="#">show source</a> ]</p>
396
+ <pre class="sourcecode">
397
+ <span class="ruby-comment cmt"># File lib/camping-unabridged.rb, line 336</span>
398
+ 336: <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">r500</span>(<span class="ruby-identifier">k</span>,<span class="ruby-identifier">m</span>,<span class="ruby-identifier">e</span>)
399
+ 337: <span class="ruby-identifier">raise</span> <span class="ruby-identifier">e</span>
400
+ 338: <span class="ruby-keyword kw">end</span></pre>
401
+ </div>
402
+
403
+ <h4 class="ruled" id="M000011">
404
+ <a href="#M000011">
405
+ Public Instance method:
406
+ <strong>#r501(m)</strong>
407
+ <img src="./images/permalink.gif">
408
+ </a>
409
+ </h4>
410
+ <div class="method">
411
+ <p>
412
+ Called if an undefined method is called on a controller, along with the
413
+ request method <tt>m</tt> (GET, POST, etc.)
414
+ </p>
415
+
416
+ <p class="source-link">[ <a href="#">show source</a> ]</p>
417
+ <pre class="sourcecode">
418
+ <span class="ruby-comment cmt"># File lib/camping-unabridged.rb, line 342</span>
419
+ 342: <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">r501</span>(<span class="ruby-identifier">m</span>)
420
+ 343: <span class="ruby-constant">P</span> <span class="ruby-operator">%</span> <span class="ruby-node">&quot;#{m.upcase} not implemented&quot;</span>
421
+ 344: <span class="ruby-keyword kw">end</span></pre>
422
+ </div>
423
+
424
+ <h4 class="ruled" id="M000008">
425
+ <a href="#M000008">
426
+ Public Instance method:
427
+ <strong>#redirect(*a)</strong>
428
+ <img src="./images/permalink.gif">
429
+ </a>
430
+ </h4>
431
+ <div class="method">
432
+ <p>
433
+ Formulate a redirect response: a 302 status with <tt>Location</tt> header
434
+ and a blank body. Uses <a href="api.html#M000004">Helpers#URL</a> to build
435
+ the location from a controller route or path.
436
+ </p>
437
+ <p>
438
+ So, given a root of <tt><a
439
+ href="http://localhost:3301/articles">localhost:3301/articles</a></tt>:
440
+ </p>
441
+ <pre>
442
+ redirect &quot;view/12&quot; # redirects to &quot;//localhost:3301/articles/view/12&quot;
443
+ redirect View, 12 # redirects to &quot;//localhost:3301/articles/view/12&quot;
444
+ </pre>
445
+ <p>
446
+ <b>NOTE:</b> This method doesn&#8217;t magically exit your methods and
447
+ redirect. You&#8217;ll need to <tt>return redirect(...)</tt> if this
448
+ isn&#8217;t the last statement in your code, or <tt>throw :halt</tt> if
449
+ it&#8217;s in a helper.
450
+ </p>
451
+ <p>
452
+ See: <a href="api.html#class-Camping-Controllers">Controllers</a>
453
+ </p>
454
+
455
+ <p class="source-link">[ <a href="#">show source</a> ]</p>
456
+ <pre class="sourcecode">
457
+ <span class="ruby-comment cmt"># File lib/camping-unabridged.rb, line 304</span>
458
+ 304: <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">redirect</span>(<span class="ruby-operator">*</span><span class="ruby-identifier">a</span>)
459
+ 305: <span class="ruby-identifier">r</span>(<span class="ruby-value">302</span>,<span class="ruby-value str">''</span>,<span class="ruby-value str">'Location'</span>=<span class="ruby-operator">&gt;</span><span class="ruby-constant">URL</span>(<span class="ruby-operator">*</span><span class="ruby-identifier">a</span>).<span class="ruby-identifier">to_s</span>)
460
+ 306: <span class="ruby-keyword kw">end</span></pre>
461
+ </div>
462
+
463
+ <h4 class="ruled" id="M000005">
464
+ <a href="#M000005">
465
+ Public Instance method:
466
+ <strong>#render(v,*a,&b)</strong>
467
+ <img src="./images/permalink.gif">
468
+ </a>
469
+ </h4>
470
+ <div class="method">
471
+ <p>
472
+ Display a view, calling it by its method name <tt>v</tt>. If a
473
+ <tt>layout</tt> method is found in <a
474
+ href="api.html#class-Camping-Views">Camping::Views</a>, it will be used to
475
+ wrap the HTML.
476
+ </p>
477
+ <pre>
478
+ module Nuts::Controllers
479
+ class Show
480
+ def get
481
+ @posts = Post.find :all
482
+ render :index
483
+ end
484
+ end
485
+ end
486
+ </pre>
487
+
488
+ <p class="source-link">[ <a href="#">show source</a> ]</p>
489
+ <pre class="sourcecode">
490
+ <span class="ruby-comment cmt"># File lib/camping-unabridged.rb, line 251</span>
491
+ 251: <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">render</span>(<span class="ruby-identifier">v</span>,<span class="ruby-operator">*</span><span class="ruby-identifier">a</span>,<span class="ruby-operator">&amp;</span><span class="ruby-identifier">b</span>)
492
+ 252: <span class="ruby-identifier">mab</span>(<span class="ruby-regexp re">/^_/</span><span class="ruby-operator">!~</span><span class="ruby-identifier">v</span>.<span class="ruby-identifier">to_s</span>){<span class="ruby-identifier">send</span>(<span class="ruby-identifier">v</span>,<span class="ruby-operator">*</span><span class="ruby-identifier">a</span>,<span class="ruby-operator">&amp;</span><span class="ruby-identifier">b</span>)}
493
+ 253: <span class="ruby-keyword kw">end</span></pre>
494
+ </div>
495
+
496
+ <h4 class="ruled" id="M000015">
497
+ <a href="#M000015">
498
+ Public Instance method:
499
+ <strong>#service(*a)</strong>
500
+ <img src="./images/permalink.gif">
501
+ </a>
502
+ </h4>
503
+ <div class="method">
504
+ <p>
505
+ All requests pass through this method before going to the controller. Some
506
+ magic in <a href="api.html#class-Camping">Camping</a> can be performed by
507
+ overriding this method.
508
+ </p>
509
+
510
+ <p class="source-link">[ <a href="#">show source</a> ]</p>
511
+ <pre class="sourcecode">
512
+ <span class="ruby-comment cmt"># File lib/camping-unabridged.rb, line 390</span>
513
+ 390: <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">service</span>(<span class="ruby-operator">*</span><span class="ruby-identifier">a</span>)
514
+ 391: <span class="ruby-identifier">r</span> = <span class="ruby-identifier">catch</span>(<span class="ruby-identifier">:halt</span>){<span class="ruby-identifier">send</span>(<span class="ruby-ivar">@method</span>, <span class="ruby-operator">*</span><span class="ruby-identifier">a</span>)}
515
+ 392: <span class="ruby-ivar">@body</span> <span class="ruby-operator">||=</span> <span class="ruby-identifier">r</span>
516
+ 393: <span class="ruby-keyword kw">self</span>
517
+ 394: <span class="ruby-keyword kw">end</span></pre>
518
+ </div>
519
+
520
+ <h4 class="ruled" id="M000012">
521
+ <a href="#M000012">
522
+ Public Instance method:
523
+ <strong>#to_a()</strong>
524
+ <img src="./images/permalink.gif">
525
+ </a>
526
+ </h4>
527
+ <div class="method">
528
+ <p>
529
+ Turn a controller into a Rack response. This is designed to be used to pipe
530
+ controllers into the <tt>r</tt> method. A great way to forward your
531
+ requests!
532
+ </p>
533
+ <pre>
534
+ class Read &lt; '/(\d+)'
535
+ def get(id)
536
+ Post.find(id)
537
+ rescue
538
+ r *Blog.get(:NotFound, @headers.REQUEST_URI)
539
+ end
540
+ end
541
+ </pre>
542
+
543
+ <p class="source-link">[ <a href="#">show source</a> ]</p>
544
+ <pre class="sourcecode">
545
+ <span class="ruby-comment cmt"># File lib/camping-unabridged.rb, line 357</span>
546
+ 357: <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">to_a</span>
547
+ 358: <span class="ruby-ivar">@env</span>[<span class="ruby-value str">'rack.session'</span>] = <span class="ruby-ivar">@state</span>
548
+ 359: <span class="ruby-identifier">r</span> = <span class="ruby-constant">Rack</span><span class="ruby-operator">::</span><span class="ruby-constant">Response</span>.<span class="ruby-identifier">new</span>(<span class="ruby-ivar">@body</span>, <span class="ruby-ivar">@status</span>, <span class="ruby-ivar">@headers</span>)
549
+ 360: <span class="ruby-ivar">@cookies</span>.<span class="ruby-identifier">each</span> <span class="ruby-keyword kw">do</span> <span class="ruby-operator">|</span><span class="ruby-identifier">k</span>, <span class="ruby-identifier">v</span><span class="ruby-operator">|</span>
550
+ 361: <span class="ruby-keyword kw">next</span> <span class="ruby-keyword kw">if</span> <span class="ruby-ivar">@old_cookies</span>[<span class="ruby-identifier">k</span>] <span class="ruby-operator">==</span> <span class="ruby-identifier">v</span>
551
+ 362: <span class="ruby-identifier">v</span> = { <span class="ruby-identifier">:value</span> =<span class="ruby-operator">&gt;</span> <span class="ruby-identifier">v</span>, <span class="ruby-identifier">:path</span> =<span class="ruby-operator">&gt;</span> <span class="ruby-keyword kw">self</span> <span class="ruby-operator">/</span> <span class="ruby-value str">&quot;/&quot;</span> } <span class="ruby-keyword kw">if</span> <span class="ruby-constant">String</span> <span class="ruby-operator">===</span> <span class="ruby-identifier">v</span>
552
+ 363: <span class="ruby-identifier">r</span>.<span class="ruby-identifier">set_cookie</span>(<span class="ruby-identifier">k</span>, <span class="ruby-identifier">v</span>)
553
+ 364: <span class="ruby-keyword kw">end</span>
554
+ 365: <span class="ruby-identifier">r</span>.<span class="ruby-identifier">to_a</span>
555
+ 366: <span class="ruby-keyword kw">end</span></pre>
556
+ </div>
557
+
558
+ </div>
559
+
560
+ <h2 id="class-Camping-Controllers">
561
+ <a href="#class-Camping-Controllers">
562
+ Module
563
+ Camping::Controllers
564
+
565
+ </a>
566
+ </h2>
567
+
568
+ <div class="mod">
569
+ <p>
570
+ <a href="api.html#class-Camping-Controllers">Controllers</a> receive the
571
+ requests and sends a response back to the client. A controller is simply a
572
+ class which must implement the HTTP methods it wants to accept:
573
+ </p>
574
+ <pre>
575
+ module Nuts::Controllers
576
+ class Index
577
+ def get
578
+ &quot;Hello World&quot;
579
+ end
580
+ end
581
+
582
+ class Posts
583
+ def post
584
+ Post.create(@input)
585
+ redirect Index
586
+ end
587
+ end
588
+ end
589
+ </pre>
590
+ <h3>Defining a controller</h3>
591
+ <p>
592
+ There are two ways to define controllers: Just defining a class and let <a
593
+ href="api.html#class-Camping">Camping</a> figure out the route, or add the
594
+ route explicitly using <a href="api.html#M000019">R</a>.
595
+ </p>
596
+ <p>
597
+ If you don&#8217;t use <a href="api.html#M000019">R</a>, <a
598
+ href="api.html#class-Camping">Camping</a> will first split the controller
599
+ name up by words (HelloWorld => Hello and World). Then it would do the
600
+ following:
601
+ </p>
602
+ <ul>
603
+ <li>Replace Index with /
604
+
605
+ </li>
606
+ <li>Replace X with ([^/]+)
607
+
608
+ </li>
609
+ <li>Replace <a href="api.html#class-Camping-Controllers#N">N</a> with (\d+)
610
+
611
+ </li>
612
+ <li>Everything else turns into lowercase
613
+
614
+ </li>
615
+ <li>Join the words with slashes
616
+
617
+ </li>
618
+ </ul>
619
+ <p>
620
+ Here&#8217;s a few examples:
621
+ </p>
622
+ <pre>
623
+ Index # =&gt; /
624
+ PostN # =&gt; /post/(\d+)
625
+ PageX # =&gt; /page/([^/]+)
626
+ Pages # =&gt; /pages
627
+ </pre>
628
+ <h3>The request</h3>
629
+ <p>
630
+ You have these variables which describes the request:
631
+ </p>
632
+ <ul>
633
+ <li>@env contains the environment as defined in <a
634
+ href="http://rack.rubyforge.org/doc/SPEC.html">rack.rubyforge.org/doc/SPEC.html</a>
635
+
636
+ </li>
637
+ <li>@request is Rack::Request.new(@env)
638
+
639
+ </li>
640
+ <li>@root is the path where the app is mounted
641
+
642
+ </li>
643
+ <li>@cookies is a hash with the cookies sent by the client
644
+
645
+ </li>
646
+ <li>@state is a hash with the sessions (see <a
647
+ href="api.html#class-Camping-Session">Camping::Session</a>)
648
+
649
+ </li>
650
+ <li>@method is the HTTP method in lowercase
651
+
652
+ </li>
653
+ </ul>
654
+ <h3>The response</h3>
655
+ <p>
656
+ You can change these variables to your needs:
657
+ </p>
658
+ <ul>
659
+ <li>@status is the HTTP status (defaults to 200)
660
+
661
+ </li>
662
+ <li>@headers is a hash with the headers
663
+
664
+ </li>
665
+ <li>@body is the body (a string or something which responds to each)
666
+
667
+ </li>
668
+ <li>Any changes in @cookies and @state will also be sent to the client
669
+
670
+ </li>
671
+ </ul>
672
+ <p>
673
+ If you haven&#8217;t set @body, it will use the return value of the method:
674
+ </p>
675
+ <pre>
676
+ module Nuts::Controllers
677
+ class Index
678
+ def get
679
+ &quot;This is the body&quot;
680
+ end
681
+ end
682
+
683
+ class Posts
684
+ def get
685
+ @body = &quot;Hello World!&quot;
686
+ &quot;This is ignored&quot;
687
+ end
688
+ end
689
+ end
690
+ </pre>
691
+
692
+
693
+ <h3>Methods</h3>
694
+
695
+ <h4 class="ruled" id="M000020">
696
+ <a href="#M000020">
697
+ Public Class method:
698
+ <strong>::D(p, m)</strong>
699
+ <img src="./images/permalink.gif">
700
+ </a>
701
+ </h4>
702
+ <div class="method">
703
+ <p>
704
+ Dispatch routes to controller classes. For each class, routes are checked
705
+ for a match based on their order in the routing list given to
706
+ Controllers::R. If no routes were given, the dispatcher uses a slash
707
+ followed by the name of the controller lowercased.
708
+ </p>
709
+ <p>
710
+ <a href="api.html#class-Camping-Controllers">Controllers</a> are searched
711
+ in this order:
712
+ </p>
713
+ <ul>
714
+ <li>Classes without routes, since they refer to a very specific URL.
715
+
716
+ </li>
717
+ <li>Classes with routes are searched in order of their creation.
718
+
719
+ </li>
720
+ </ul>
721
+ <p>
722
+ So, define your catch-all controllers last.
723
+ </p>
724
+
725
+ <p class="source-link">[ <a href="#">show source</a> ]</p>
726
+ <pre class="sourcecode">
727
+ <span class="ruby-comment cmt"># File lib/camping-unabridged.rb, line 520</span>
728
+ 520: <span class="ruby-keyword kw">def</span> <span class="ruby-constant">D</span>(<span class="ruby-identifier">p</span>, <span class="ruby-identifier">m</span>)
729
+ 521: <span class="ruby-identifier">p</span> = <span class="ruby-value str">'/'</span> <span class="ruby-keyword kw">if</span> <span class="ruby-operator">!</span><span class="ruby-identifier">p</span> <span class="ruby-operator">||</span> <span class="ruby-operator">!</span><span class="ruby-identifier">p</span>[<span class="ruby-value">0</span>]
730
+ 522: <span class="ruby-identifier">r</span>.<span class="ruby-identifier">map</span> { <span class="ruby-operator">|</span><span class="ruby-identifier">k</span><span class="ruby-operator">|</span>
731
+ 523: <span class="ruby-identifier">k</span>.<span class="ruby-identifier">urls</span>.<span class="ruby-identifier">map</span> { <span class="ruby-operator">|</span><span class="ruby-identifier">x</span><span class="ruby-operator">|</span>
732
+ 524: <span class="ruby-keyword kw">return</span> (<span class="ruby-identifier">k</span>.<span class="ruby-identifier">instance_method</span>(<span class="ruby-identifier">m</span>) <span class="ruby-keyword kw">rescue</span> <span class="ruby-keyword kw">nil</span>) <span class="ruby-operator">?</span>
733
+ 525: [<span class="ruby-identifier">k</span>, <span class="ruby-identifier">m</span>, <span class="ruby-operator">*</span><span class="ruby-identifier">$~</span>[<span class="ruby-value">1</span><span class="ruby-operator">..</span><span class="ruby-value">-1</span>]] <span class="ruby-operator">:</span> [<span class="ruby-constant">I</span>, <span class="ruby-value str">'r501'</span>, <span class="ruby-identifier">m</span>] <span class="ruby-keyword kw">if</span> <span class="ruby-identifier">p</span> <span class="ruby-operator">=~</span> <span class="ruby-node">/^#{x}\/?$/</span>
734
+ 526: }
735
+ 527: }
736
+ 528: [<span class="ruby-constant">I</span>, <span class="ruby-value str">'r404'</span>, <span class="ruby-identifier">p</span>]
737
+ 529: <span class="ruby-keyword kw">end</span></pre>
738
+ </div>
739
+
740
+ <h4 class="ruled" id="M000021">
741
+ <a href="#M000021">
742
+ Public Class method:
743
+ <strong>::M()</strong>
744
+ <img src="./images/permalink.gif">
745
+ </a>
746
+ </h4>
747
+ <div class="method">
748
+ <p>
749
+ The route maker, this is called by <a
750
+ href="api.html#class-Camping">Camping</a> internally, you shouldn&#8217;t
751
+ need to call it.
752
+ </p>
753
+ <p>
754
+ Still, it&#8217;s worth know what this method does. Since Ruby
755
+ doesn&#8217;t keep track of class creation order, we&#8217;re keeping an
756
+ internal list of the controllers which inherit from R(). This method goes
757
+ through and adds all the remaining routes to the beginning of the list and
758
+ ensures all the controllers have the right mixins.
759
+ </p>
760
+ <p>
761
+ Anyway, if you are calling the URI dispatcher from outside of a <a
762
+ href="api.html#class-Camping">Camping</a> server, you&#8217;ll definitely
763
+ need to call this to set things up. Don&#8217;t call it too early though.
764
+ Any controllers added after this method is called won&#8217;t work properly
765
+ </p>
766
+
767
+ <p class="source-link">[ <a href="#">show source</a> ]</p>
768
+ <pre class="sourcecode">
769
+ <span class="ruby-comment cmt"># File lib/camping-unabridged.rb, line 545</span>
770
+ 545: <span class="ruby-keyword kw">def</span> <span class="ruby-constant">M</span>
771
+ 546: <span class="ruby-keyword kw">def</span> <span class="ruby-constant">M</span> <span class="ruby-comment cmt">#:nodoc:</span>
772
+ 547: <span class="ruby-keyword kw">end</span>
773
+ 548: <span class="ruby-identifier">constants</span>.<span class="ruby-identifier">map</span> { <span class="ruby-operator">|</span><span class="ruby-identifier">c</span><span class="ruby-operator">|</span>
774
+ 549: <span class="ruby-identifier">k</span> = <span class="ruby-identifier">const_get</span>(<span class="ruby-identifier">c</span>)
775
+ 550: <span class="ruby-identifier">k</span>.<span class="ruby-identifier">send</span> <span class="ruby-identifier">:include</span>,<span class="ruby-constant">C</span>,<span class="ruby-constant">Base</span>,<span class="ruby-constant">Helpers</span>,<span class="ruby-constant">Models</span>
776
+ 551: <span class="ruby-ivar">@r</span>=[<span class="ruby-identifier">k</span>]<span class="ruby-operator">+</span><span class="ruby-identifier">r</span> <span class="ruby-keyword kw">if</span> <span class="ruby-identifier">r</span><span class="ruby-operator">-</span>[<span class="ruby-identifier">k</span>]<span class="ruby-operator">==</span><span class="ruby-identifier">r</span>
777
+ 552: <span class="ruby-identifier">k</span>.<span class="ruby-identifier">meta_def</span>(<span class="ruby-identifier">:urls</span>){[<span class="ruby-node">&quot;/#{c.scan(/.[^A-Z]*/).map(&amp;N.method(:[]))*'/'}&quot;</span>]}<span class="ruby-keyword kw">if</span> <span class="ruby-operator">!</span><span class="ruby-identifier">k</span>.<span class="ruby-identifier">respond_to?</span><span class="ruby-identifier">:urls</span>
778
+ 553: }
779
+ 554: <span class="ruby-keyword kw">end</span></pre>
780
+ </div>
781
+
782
+ <h4 class="ruled" id="M000019">
783
+ <a href="#M000019">
784
+ Public Class method:
785
+ <strong>::R(*u)</strong>
786
+ <img src="./images/permalink.gif">
787
+ </a>
788
+ </h4>
789
+ <div class="method">
790
+ <p>
791
+ Add routes to a controller class by piling them into the <a
792
+ href="api.html#M000019">R</a> method.
793
+ </p>
794
+ <p>
795
+ The route is a regexp which will match the request path. Anything enclosed
796
+ in parenthesis will be sent to the method as arguments.
797
+ </p>
798
+ <pre>
799
+ module Camping::Controllers
800
+ class Edit &lt; R '/edit/(\d+)', '/new'
801
+ def get(id)
802
+ if id # edit
803
+ else # new
804
+ end
805
+ end
806
+ end
807
+ end
808
+ </pre>
809
+
810
+ <p class="source-link">[ <a href="#">show source</a> ]</p>
811
+ <pre class="sourcecode">
812
+ <span class="ruby-comment cmt"># File lib/camping-unabridged.rb, line 501</span>
813
+ 501: <span class="ruby-keyword kw">def</span> <span class="ruby-constant">R</span> <span class="ruby-operator">*</span><span class="ruby-identifier">u</span>
814
+ 502: <span class="ruby-identifier">r</span>=<span class="ruby-ivar">@r</span>
815
+ 503: <span class="ruby-constant">Class</span>.<span class="ruby-identifier">new</span> {
816
+ 504: <span class="ruby-identifier">meta_def</span>(<span class="ruby-identifier">:urls</span>){<span class="ruby-identifier">u</span>}
817
+ 505: <span class="ruby-identifier">meta_def</span>(<span class="ruby-identifier">:inherited</span>){<span class="ruby-operator">|</span><span class="ruby-identifier">x</span><span class="ruby-operator">|</span><span class="ruby-identifier">r</span><span class="ruby-operator">&lt;&lt;</span><span class="ruby-identifier">x</span>}
818
+ 506: }
819
+ 507: <span class="ruby-keyword kw">end</span></pre>
820
+ </div>
821
+
822
+ </div>
823
+
824
+ <h2 id="class-Camping-H">
825
+ <a href="#class-Camping-H">
826
+ Class
827
+ Camping::H
828
+
829
+ &lt;
830
+
831
+ Hash
832
+
833
+
834
+ </a>
835
+ </h2>
836
+
837
+ <div class="mod">
838
+ <p>
839
+ An object-like Hash. All <a href="api.html#class-Camping">Camping</a> query
840
+ string and cookie variables are loaded as this.
841
+ </p>
842
+ <p>
843
+ To access the query string, for instance, use the <tt>@input</tt> variable.
844
+ </p>
845
+ <pre>
846
+ module Blog::Controllers
847
+ class Index &lt; R '/'
848
+ def get
849
+ if (page = @input.page.to_i) &gt; 0
850
+ page -= 1
851
+ end
852
+ @posts = Post.all, :offset =&gt; page * 20, :limit =&gt; 20
853
+ render :index
854
+ end
855
+ end
856
+ end
857
+ </pre>
858
+ <p>
859
+ In the above example if you visit <tt>/?page=2</tt>, you&#8217;ll get the
860
+ second page of twenty posts. You can also use <tt>@input['page']</tt> to
861
+ get the value for the <tt>page</tt> query variable.
862
+ </p>
863
+
864
+
865
+ <h3>Methods</h3>
866
+
867
+ <h4 class="ruled" id="M000001">
868
+ <a href="#M000001">
869
+ Public Instance method:
870
+ <strong>#method_missing(m,*a)</strong>
871
+ <img src="./images/permalink.gif">
872
+ </a>
873
+ </h4>
874
+ <div class="method">
875
+ <p>
876
+ Gets or sets keys in the hash.
877
+ </p>
878
+ <pre>
879
+ @cookies.my_favorite = :macadamian
880
+ @cookies.my_favorite
881
+ =&gt; :macadamian
882
+ </pre>
883
+
884
+ <p class="source-link">[ <a href="#">show source</a> ]</p>
885
+ <pre class="sourcecode">
886
+ <span class="ruby-comment cmt"># File lib/camping-unabridged.rb, line 77</span>
887
+ 77: <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">method_missing</span>(<span class="ruby-identifier">m</span>,<span class="ruby-operator">*</span><span class="ruby-identifier">a</span>)
888
+ 78: <span class="ruby-identifier">m</span>.<span class="ruby-identifier">to_s</span><span class="ruby-operator">=~</span><span class="ruby-regexp re">/=$/</span><span class="ruby-operator">?</span><span class="ruby-keyword kw">self</span>[<span class="ruby-identifier">$`</span>]=<span class="ruby-identifier">a</span>[<span class="ruby-value">0</span>]<span class="ruby-operator">:</span><span class="ruby-identifier">a</span><span class="ruby-operator">==</span>[]<span class="ruby-operator">?</span><span class="ruby-keyword kw">self</span>[<span class="ruby-identifier">m</span>.<span class="ruby-identifier">to_s</span>]<span class="ruby-operator">:</span><span class="ruby-keyword kw">super</span>
889
+ 79: <span class="ruby-keyword kw">end</span></pre>
890
+ </div>
891
+
892
+ </div>
893
+
894
+ <h2 id="class-Camping-Helpers">
895
+ <a href="#class-Camping-Helpers">
896
+ Module
897
+ Camping::Helpers
898
+
899
+ </a>
900
+ </h2>
901
+
902
+ <div class="mod">
903
+ <p>
904
+ <a href="api.html#class-Camping-Helpers">Helpers</a> contains methods
905
+ available in your controllers and views. You may add methods of your own to
906
+ this module, including many helper methods from Rails. This is analogous to
907
+ Rails&#8217; <tt>ApplicationHelper</tt> module.
908
+ </p>
909
+ <h3>Using ActionPack <a href="api.html#class-Camping-Helpers">Helpers</a></h3>
910
+ <p>
911
+ If you&#8217;d like to include helpers from Rails&#8217; modules,
912
+ you&#8217;ll need to look up the helper module in the Rails documentation
913
+ at <a href="http://api.rubyonrails.org/.">api.rubyonrails.org/.</a>
914
+ </p>
915
+ <p>
916
+ For example, if you look up the <tt>ActionView::Helpers::FormTagHelper</tt>
917
+ class, you&#8217;ll find that it&#8217;s loaded from the
918
+ <tt>action_view/helpers/form_tag_helper.rb</tt> file. You&#8217;ll need to
919
+ have the ActionPack gem installed for this to work.
920
+ </p>
921
+ <p>
922
+ Often the helpers depends on other helpers, so you would have to look up
923
+ the dependencies too. <tt>FormTagHelper</tt> for instance required the
924
+ <tt>content_tag</tt> provided by <tt>TagHelper</tt>.
925
+ </p>
926
+ <pre>
927
+ require 'action_view/helpers/form_tag_helper'
928
+
929
+ module Nuts::Helpers
930
+ include ActionView::Helpers::TagHelper
931
+ include ActionView::Helpers::FormTagHelper
932
+ end
933
+ </pre>
934
+ <h3>Return a response immediately</h3>
935
+ <p>
936
+ If you need to return a response inside a helper, you can use <tt>throw
937
+ :halt</tt>.
938
+ </p>
939
+ <pre>
940
+ module Nuts::Helpers
941
+ def requires_login!
942
+ unless @state.user_id
943
+ redirect Login
944
+ throw :halt
945
+ end
946
+ end
947
+ end
948
+
949
+ module Nuts::Controllers
950
+ class Admin
951
+ def get
952
+ requires_login!
953
+ &quot;Never gets here unless you're logged in&quot;
954
+ end
955
+ end
956
+ end
957
+ </pre>
958
+
959
+
960
+ <h3>Methods</h3>
961
+
962
+ <h4 class="ruled" id="M000003">
963
+ <a href="#M000003">
964
+ Public Instance method:
965
+ <strong>#/(p)</strong>
966
+ <img src="./images/permalink.gif">
967
+ </a>
968
+ </h4>
969
+ <div class="method">
970
+ <p>
971
+ Simply builds a complete path from a path <tt>p</tt> within the app. If
972
+ your application is mounted at <tt>/blog</tt>:
973
+ </p>
974
+ <pre>
975
+ self / &quot;/view/1&quot; #=&gt; &quot;/blog/view/1&quot;
976
+ self / &quot;styles.css&quot; #=&gt; &quot;styles.css&quot;
977
+ self / R(Edit, 1) #=&gt; &quot;/blog/edit/1&quot;
978
+ </pre>
979
+
980
+ <p class="source-link">[ <a href="#">show source</a> ]</p>
981
+ <pre class="sourcecode">
982
+ <span class="ruby-comment cmt"># File lib/camping-unabridged.rb, line 198</span>
983
+ 198: <span class="ruby-keyword kw">def</span> <span class="ruby-operator">/</span>(<span class="ruby-identifier">p</span>); <span class="ruby-identifier">p</span>[<span class="ruby-value">0</span>]<span class="ruby-operator">==</span><span class="ruby-value">?/</span><span class="ruby-operator">?</span><span class="ruby-ivar">@root</span><span class="ruby-operator">+</span><span class="ruby-identifier">p</span><span class="ruby-identifier">:p</span> <span class="ruby-keyword kw">end</span></pre>
984
+ </div>
985
+
986
+ <h4 class="ruled" id="M000002">
987
+ <a href="#M000002">
988
+ Public Instance method:
989
+ <strong>#R(c,*g)</strong>
990
+ <img src="./images/permalink.gif">
991
+ </a>
992
+ </h4>
993
+ <div class="method">
994
+ <p>
995
+ From inside your controllers and views, you will often need to figure out
996
+ the route used to get to a certain controller <tt>c</tt>. Pass the
997
+ controller class and any arguments into the <a
998
+ href="api.html#M000002">R</a> method, a string containing the route will be
999
+ returned to you.
1000
+ </p>
1001
+ <p>
1002
+ Assuming you have a specific route in an edit controller:
1003
+ </p>
1004
+ <pre>
1005
+ class Edit &lt; R '/edit/(\d+)'
1006
+ </pre>
1007
+ <p>
1008
+ A specific route to the Edit controller can be built with:
1009
+ </p>
1010
+ <pre>
1011
+ R(Edit, 1)
1012
+ </pre>
1013
+ <p>
1014
+ Which outputs: <tt>/edit/1</tt>.
1015
+ </p>
1016
+ <p>
1017
+ If a controller has many routes, the route will be selected if it is the
1018
+ first in the routing list to have the right number of arguments.
1019
+ </p>
1020
+ <h2>Using <a href="api.html#M000002">R</a> in the View</h2>
1021
+ <p>
1022
+ Keep in mind that this route doesn&#8217;t include the root path. You will
1023
+ need to use <tt>/</tt> (the slash method above) in your controllers. Or, go
1024
+ ahead and use the <a href="api.html#M000004">Helpers#URL</a> method to
1025
+ build a complete <a href="api.html#M000004">URL</a> for a route.
1026
+ </p>
1027
+ <p>
1028
+ However, in your views, the :href, :src and :action attributes
1029
+ automatically pass through the slash method, so you are encouraged to use
1030
+ <tt>R</tt> or <tt>URL</tt> in your views.
1031
+ </p>
1032
+ <pre>
1033
+ module Nuts::Views
1034
+ def menu
1035
+ div.menu! do
1036
+ a 'Home', :href =&gt; URL()
1037
+ a 'Profile', :href =&gt; &quot;/profile&quot;
1038
+ a 'Logout', :href =&gt; R(Logout)
1039
+ a 'Google', :href =&gt; 'http://google.com'
1040
+ end
1041
+ end
1042
+ end
1043
+ </pre>
1044
+ <p>
1045
+ Let&#8217;s say the above example takes place inside an application mounted
1046
+ at <tt><a href="http://localhost:3301/frodo">localhost:3301/frodo</a></tt>
1047
+ and that a controller named <tt>Logout</tt> is assigned to route
1048
+ <tt>/logout</tt>. The HTML will come out as:
1049
+ </p>
1050
+ <pre>
1051
+ &lt;div id=&quot;menu&quot;&gt;
1052
+ &lt;a href=&quot;http://localhost:3301/frodo/&quot;&gt;Home&lt;/a&gt;
1053
+ &lt;a href=&quot;/frodo/profile&quot;&gt;Profile&lt;/a&gt;
1054
+ &lt;a href=&quot;/frodo/logout&quot;&gt;Logout&lt;/a&gt;
1055
+ &lt;a href=&quot;http://google.com&quot;&gt;Google&lt;/a&gt;
1056
+ &lt;/div&gt;
1057
+ </pre>
1058
+
1059
+ <p class="source-link">[ <a href="#">show source</a> ]</p>
1060
+ <pre class="sourcecode">
1061
+ <span class="ruby-comment cmt"># File lib/camping-unabridged.rb, line 180</span>
1062
+ 180: <span class="ruby-keyword kw">def</span> <span class="ruby-constant">R</span>(<span class="ruby-identifier">c</span>,<span class="ruby-operator">*</span><span class="ruby-identifier">g</span>)
1063
+ 181: <span class="ruby-identifier">p</span>,<span class="ruby-identifier">h</span>=<span class="ruby-regexp re">/\(.+?\)/</span>,<span class="ruby-identifier">g</span>.<span class="ruby-identifier">grep</span>(<span class="ruby-constant">Hash</span>)
1064
+ 182: <span class="ruby-identifier">g</span><span class="ruby-operator">-=</span><span class="ruby-identifier">h</span>
1065
+ 183: <span class="ruby-identifier">raise</span> <span class="ruby-value str">&quot;bad route&quot;</span> <span class="ruby-keyword kw">unless</span> <span class="ruby-identifier">u</span> = <span class="ruby-identifier">c</span>.<span class="ruby-identifier">urls</span>.<span class="ruby-identifier">find</span>{<span class="ruby-operator">|</span><span class="ruby-identifier">x</span><span class="ruby-operator">|</span>
1066
+ 184: <span class="ruby-keyword kw">break</span> <span class="ruby-identifier">x</span> <span class="ruby-keyword kw">if</span> <span class="ruby-identifier">x</span>.<span class="ruby-identifier">scan</span>(<span class="ruby-identifier">p</span>).<span class="ruby-identifier">size</span> <span class="ruby-operator">==</span> <span class="ruby-identifier">g</span>.<span class="ruby-identifier">size</span> <span class="ruby-operator">&amp;&amp;</span>
1067
+ 185: <span class="ruby-node">/^#{x}\/?$/</span> <span class="ruby-operator">=~</span> (<span class="ruby-identifier">x</span>=<span class="ruby-identifier">g</span>.<span class="ruby-identifier">inject</span>(<span class="ruby-identifier">x</span>){<span class="ruby-operator">|</span><span class="ruby-identifier">x</span>,<span class="ruby-identifier">a</span><span class="ruby-operator">|</span>
1068
+ 186: <span class="ruby-identifier">x</span>.<span class="ruby-identifier">sub</span> <span class="ruby-identifier">p</span>,<span class="ruby-constant">U</span>.<span class="ruby-identifier">escape</span>((<span class="ruby-identifier">a</span>[<span class="ruby-identifier">a</span>.<span class="ruby-identifier">class</span>.<span class="ruby-identifier">primary_key</span>]<span class="ruby-keyword kw">rescue</span> <span class="ruby-identifier">a</span>))})
1069
+ 187: }
1070
+ 188: <span class="ruby-identifier">h</span>.<span class="ruby-identifier">any?</span><span class="ruby-value">? </span><span class="ruby-identifier">u</span><span class="ruby-operator">+</span><span class="ruby-value str">&quot;?&quot;</span><span class="ruby-operator">+</span><span class="ruby-constant">U</span>.<span class="ruby-identifier">build_query</span>(<span class="ruby-identifier">h</span>[<span class="ruby-value">0</span>]) <span class="ruby-operator">:</span> <span class="ruby-identifier">u</span>
1071
+ 189: <span class="ruby-keyword kw">end</span></pre>
1072
+ </div>
1073
+
1074
+ <h4 class="ruled" id="M000004">
1075
+ <a href="#M000004">
1076
+ Public Instance method:
1077
+ <strong>#URL(c='/',*a)</strong>
1078
+ <img src="./images/permalink.gif">
1079
+ </a>
1080
+ </h4>
1081
+ <div class="method">
1082
+ <p>
1083
+ Builds a <a href="api.html#M000004">URL</a> route to a controller or a
1084
+ path, returning a URI object. This way you&#8217;ll get the hostname and
1085
+ the port number, a complete <a href="api.html#M000004">URL</a>.
1086
+ </p>
1087
+ <p>
1088
+ You can use this to grab URLs for controllers using the R-style syntax. So,
1089
+ if your application is mounted at <tt><a
1090
+ href="http://test.ing/blog/">test.ing/blog/</a></tt> and you have a View
1091
+ controller which routes as <tt><a href="api.html#M000002">R</a>
1092
+ '/view/(d+)'</tt>:
1093
+ </p>
1094
+ <pre>
1095
+ URL(View, @post.id) #=&gt; #&lt;URL:http://test.ing/blog/view/12&gt;
1096
+ </pre>
1097
+ <p>
1098
+ Or you can use the direct path:
1099
+ </p>
1100
+ <pre>
1101
+ self.URL #=&gt; #&lt;URL:http://test.ing/blog/&gt;
1102
+ self.URL + &quot;view/12&quot; #=&gt; #&lt;URL:http://test.ing/blog/view/12&gt;
1103
+ URL(&quot;/view/12&quot;) #=&gt; #&lt;URL:http://test.ing/blog/view/12&gt;
1104
+ </pre>
1105
+ <p>
1106
+ It&#8217;s okay to pass <a href="api.html#M000004">URL</a> strings through
1107
+ this method as well:
1108
+ </p>
1109
+ <pre>
1110
+ URL(&quot;http://google.com&quot;) #=&gt; #&lt;URL:http://google.com&gt;
1111
+ </pre>
1112
+ <p>
1113
+ Any string which doesn&#8217;t begin with a slash will pass through
1114
+ unscathed.
1115
+ </p>
1116
+
1117
+ <p class="source-link">[ <a href="#">show source</a> ]</p>
1118
+ <pre class="sourcecode">
1119
+ <span class="ruby-comment cmt"># File lib/camping-unabridged.rb, line 221</span>
1120
+ 221: <span class="ruby-keyword kw">def</span> <span class="ruby-constant">URL</span> <span class="ruby-identifier">c</span>=<span class="ruby-value str">'/'</span>,<span class="ruby-operator">*</span><span class="ruby-identifier">a</span>
1121
+ 222: <span class="ruby-identifier">c</span> = <span class="ruby-constant">R</span>(<span class="ruby-identifier">c</span>, <span class="ruby-operator">*</span><span class="ruby-identifier">a</span>) <span class="ruby-keyword kw">if</span> <span class="ruby-identifier">c</span>.<span class="ruby-identifier">respond_to?</span> <span class="ruby-identifier">:urls</span>
1122
+ 223: <span class="ruby-identifier">c</span> = <span class="ruby-keyword kw">self</span><span class="ruby-operator">/</span><span class="ruby-identifier">c</span>
1123
+ 224: <span class="ruby-identifier">c</span> = <span class="ruby-ivar">@request</span>.<span class="ruby-identifier">url</span>[<span class="ruby-regexp re">/.{8,}?(?=\/)/</span>]<span class="ruby-operator">+</span><span class="ruby-identifier">c</span> <span class="ruby-keyword kw">if</span> <span class="ruby-identifier">c</span>[<span class="ruby-value">0</span>]<span class="ruby-operator">==</span><span class="ruby-value">?/</span>
1124
+ 225: <span class="ruby-constant">URI</span>(<span class="ruby-identifier">c</span>)
1125
+ 226: <span class="ruby-keyword kw">end</span></pre>
1126
+ </div>
1127
+
1128
+ </div>
1129
+
1130
+ <h2 id="class-Camping-Models">
1131
+ <a href="#class-Camping-Models">
1132
+ Module
1133
+ Camping::Models
1134
+
1135
+ </a>
1136
+ </h2>
1137
+
1138
+ <div class="mod">
1139
+ <p>
1140
+ <a href="api.html#class-Camping-Models">Models</a> is an empty Ruby module
1141
+ for housing model classes derived from ActiveRecord::Base. As a shortcut,
1142
+ you may derive from <a href="api.html#class-Camping-Models#Base">Base</a>
1143
+ which is an alias for ActiveRecord::Base.
1144
+ </p>
1145
+ <pre>
1146
+ module Camping::Models
1147
+ class Post &lt; Base; belongs_to :user end
1148
+ class User &lt; Base; has_many :posts end
1149
+ end
1150
+ </pre>
1151
+ <h3>Where <a href="api.html#class-Camping-Models">Models</a> are Used</h3>
1152
+ <p>
1153
+ <a href="api.html#class-Camping-Models">Models</a> are used in your
1154
+ controller classes. However, if your model class name conflicts with a
1155
+ controller class name, you will need to refer to it using the <a
1156
+ href="api.html#class-Camping-Models">Models</a> module.
1157
+ </p>
1158
+ <pre>
1159
+ module Camping::Controllers
1160
+ class Post &lt; R '/post/(\d+)'
1161
+ def get(post_id)
1162
+ @post = Models::Post.find post_id
1163
+ render :index
1164
+ end
1165
+ end
1166
+ end
1167
+ </pre>
1168
+ <p>
1169
+ <a href="api.html#class-Camping-Models">Models</a> cannot be referred to in
1170
+ <a href="api.html#class-Camping-Views">Views</a> at this time.
1171
+ </p>
1172
+
1173
+
1174
+ <h3>Methods</h3>
1175
+
1176
+ </div>
1177
+
1178
+ <h2 id="class-Camping-Models-Base">
1179
+ <a href="#class-Camping-Models-Base">
1180
+ Module
1181
+ Camping::Models::Base
1182
+
1183
+ </a>
1184
+ </h2>
1185
+
1186
+ <div class="mod">
1187
+
1188
+
1189
+ <h3>Methods</h3>
1190
+
1191
+ <h4 class="ruled" id="M000000">
1192
+ <a href="#M000000">
1193
+ Public Class method:
1194
+ <strong>::table_name_prefix()</strong>
1195
+ <img src="./images/permalink.gif">
1196
+ </a>
1197
+ </h4>
1198
+ <div class="method">
1199
+ <p>
1200
+ The default prefix for <a href="api.html#class-Camping">Camping</a> model
1201
+ classes is the topmost module name lowercase and followed with an
1202
+ underscore.
1203
+ </p>
1204
+ <pre>
1205
+ Tepee::Models::Page.table_name_prefix
1206
+ #=&gt; &quot;tepee_pages&quot;
1207
+ </pre>
1208
+
1209
+ <p class="source-link">[ <a href="#">show source</a> ]</p>
1210
+ <pre class="sourcecode">
1211
+ <span class="ruby-comment cmt"># File lib/camping/ar.rb, line 66</span>
1212
+ 66: <span class="ruby-keyword kw">def</span> <span class="ruby-constant">Base</span>.<span class="ruby-identifier">table_name_prefix</span>
1213
+ 67: <span class="ruby-node">&quot;#{name[/\w+/]}_&quot;</span>.<span class="ruby-identifier">downcase</span>.<span class="ruby-identifier">sub</span>(<span class="ruby-node">/^(#{A}|camping)_/i</span>,<span class="ruby-value str">''</span>)
1214
+ 68: <span class="ruby-keyword kw">end</span></pre>
1215
+ </div>
1216
+
1217
+ </div>
1218
+
1219
+ <h2 id="class-Camping-Reloader">
1220
+ <a href="#class-Camping-Reloader">
1221
+ Class
1222
+ Camping::Reloader
1223
+
1224
+ &lt;
1225
+
1226
+ Object
1227
+
1228
+
1229
+ </a>
1230
+ </h2>
1231
+
1232
+ <div class="mod">
1233
+ <h3>The <a href="api.html#class-Camping">Camping</a> <a href="api.html#class-Camping-Reloader">Reloader</a></h3>
1234
+ <p>
1235
+ <a href="api.html#class-Camping">Camping</a> apps are generally small and
1236
+ predictable. Many <a href="api.html#class-Camping">Camping</a> apps are
1237
+ contained within a single file. Larger apps are split into a handful of
1238
+ other Ruby libraries within the same directory.
1239
+ </p>
1240
+ <p>
1241
+ Since <a href="api.html#class-Camping">Camping</a> apps (and their
1242
+ dependencies) are loaded with Ruby&#8217;s require method, there is a
1243
+ record of them in $LOADED_FEATURES. Which leaves a perfect space for this
1244
+ class to manage auto-reloading an app if any of its immediate dependencies
1245
+ changes.
1246
+ </p>
1247
+ <h3>Wrapping Your Apps</h3>
1248
+ <p>
1249
+ Since bin/camping and the <a
1250
+ href="api.html#class-Camping-Server">Camping::Server</a> class already use
1251
+ the <a href="api.html#class-Camping-Reloader">Reloader</a>, you probably
1252
+ don&#8217;t need to hack it on your own. But, if you&#8217;re rolling your
1253
+ own situation, here&#8217;s how.
1254
+ </p>
1255
+ <p>
1256
+ Rather than this:
1257
+ </p>
1258
+ <pre>
1259
+ require 'yourapp'
1260
+ </pre>
1261
+ <p>
1262
+ Use this:
1263
+ </p>
1264
+ <pre>
1265
+ require 'camping/reloader'
1266
+ reloader = Camping::Reloader.new('/path/to/yourapp.rb')
1267
+ blog = reloader.apps[:Blog]
1268
+ wiki = reloader.apps[:Wiki]
1269
+ </pre>
1270
+ <p>
1271
+ The <tt>blog</tt> and <tt>wiki</tt> objects will behave exactly like your
1272
+ Blog and Wiki, but they will update themselves if yourapp.rb changes.
1273
+ </p>
1274
+ <p>
1275
+ You can also give <a href="api.html#class-Camping-Reloader">Reloader</a>
1276
+ more than one script.
1277
+ </p>
1278
+
1279
+
1280
+ <h3>Methods</h3>
1281
+
1282
+ <h4 class="ruled" id="M000025">
1283
+ <a href="#M000025">
1284
+ Public Class method:
1285
+ <strong>::new(*scripts)</strong>
1286
+ <img src="./images/permalink.gif">
1287
+ </a>
1288
+ </h4>
1289
+ <div class="method">
1290
+ <p>
1291
+ Creates the reloader, assigns a <tt>script</tt> to it and initially loads
1292
+ the application. Pass in the full path to the script, otherwise the script
1293
+ will be loaded relative to the current working directory.
1294
+ </p>
1295
+
1296
+ <p class="source-link">[ <a href="#">show source</a> ]</p>
1297
+ <pre class="sourcecode">
1298
+ <span class="ruby-comment cmt"># File lib/camping/reloader.rb, line 150</span>
1299
+ 150: <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">initialize</span>(<span class="ruby-operator">*</span><span class="ruby-identifier">scripts</span>)
1300
+ 151: <span class="ruby-ivar">@scripts</span> = []
1301
+ 152: <span class="ruby-identifier">update</span>(<span class="ruby-operator">*</span><span class="ruby-identifier">scripts</span>)
1302
+ 153: <span class="ruby-keyword kw">end</span></pre>
1303
+ </div>
1304
+
1305
+ <h4 class="ruled" id="M000030">
1306
+ <a href="#M000030">
1307
+ Public Instance method:
1308
+ <strong>#apps()</strong>
1309
+ <img src="./images/permalink.gif">
1310
+ </a>
1311
+ </h4>
1312
+ <div class="method">
1313
+ <p>
1314
+ Returns a Hash of all the apps available in the scripts, where the key
1315
+ would be the name of the app (the one you gave to <a
1316
+ href="api.html#M000023">Camping.goes</a>) and the value would be the app
1317
+ (wrapped inside <a href="api.html#class-Camping-Reloader-App">App</a>).
1318
+ </p>
1319
+
1320
+ <p class="source-link">[ <a href="#">show source</a> ]</p>
1321
+ <pre class="sourcecode">
1322
+ <span class="ruby-comment cmt"># File lib/camping/reloader.rb, line 185</span>
1323
+ 185: <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">apps</span>
1324
+ 186: <span class="ruby-ivar">@scripts</span>.<span class="ruby-identifier">inject</span>({}) <span class="ruby-keyword kw">do</span> <span class="ruby-operator">|</span><span class="ruby-identifier">hash</span>, <span class="ruby-identifier">script</span><span class="ruby-operator">|</span>
1325
+ 187: <span class="ruby-identifier">hash</span>.<span class="ruby-identifier">merge</span>(<span class="ruby-identifier">script</span>.<span class="ruby-identifier">apps</span>)
1326
+ 188: <span class="ruby-keyword kw">end</span>
1327
+ 189: <span class="ruby-keyword kw">end</span></pre>
1328
+ </div>
1329
+
1330
+ <h4 class="ruled" id="M000028">
1331
+ <a href="#M000028">
1332
+ Public Instance method:
1333
+ <strong>#clear()</strong>
1334
+ <img src="./images/permalink.gif">
1335
+ </a>
1336
+ </h4>
1337
+ <div class="method">
1338
+ <p>
1339
+ Removes all the scripts from the reloader.
1340
+ </p>
1341
+
1342
+ <p class="source-link">[ <a href="#">show source</a> ]</p>
1343
+ <pre class="sourcecode">
1344
+ <span class="ruby-comment cmt"># File lib/camping/reloader.rb, line 173</span>
1345
+ 173: <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">clear</span>
1346
+ 174: <span class="ruby-ivar">@scrips</span> = []
1347
+ 175: <span class="ruby-keyword kw">end</span></pre>
1348
+ </div>
1349
+
1350
+ <h4 class="ruled" id="M000029">
1351
+ <a href="#M000029">
1352
+ Public Instance method:
1353
+ <strong>#reload!()</strong>
1354
+ <img src="./images/permalink.gif">
1355
+ </a>
1356
+ </h4>
1357
+ <div class="method">
1358
+ <p>
1359
+ Simply calls reload! on all the Script objects.
1360
+ </p>
1361
+
1362
+ <p class="source-link">[ <a href="#">show source</a> ]</p>
1363
+ <pre class="sourcecode">
1364
+ <span class="ruby-comment cmt"># File lib/camping/reloader.rb, line 178</span>
1365
+ 178: <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">reload!</span>
1366
+ 179: <span class="ruby-ivar">@scripts</span>.<span class="ruby-identifier">each</span> { <span class="ruby-operator">|</span><span class="ruby-identifier">script</span><span class="ruby-operator">|</span> <span class="ruby-identifier">script</span>.<span class="ruby-identifier">reload!</span> }
1367
+ 180: <span class="ruby-keyword kw">end</span></pre>
1368
+ </div>
1369
+
1370
+ <h4 class="ruled" id="M000026">
1371
+ <a href="#M000026">
1372
+ Public Instance method:
1373
+ <strong>#update(*scripts)</strong>
1374
+ <img src="./images/permalink.gif">
1375
+ </a>
1376
+ </h4>
1377
+ <div class="method">
1378
+ <p>
1379
+ Updates the reloader to only use the scripts provided:
1380
+ </p>
1381
+ <pre>
1382
+ reloader.update(&quot;examples/blog.rb&quot;, &quot;examples/wiki.rb&quot;)
1383
+ </pre>
1384
+
1385
+ <p class="source-link">[ <a href="#">show source</a> ]</p>
1386
+ <pre class="sourcecode">
1387
+ <span class="ruby-comment cmt"># File lib/camping/reloader.rb, line 158</span>
1388
+ 158: <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">update</span>(<span class="ruby-operator">*</span><span class="ruby-identifier">scripts</span>)
1389
+ 159: <span class="ruby-identifier">old</span> = <span class="ruby-ivar">@scripts</span>.<span class="ruby-identifier">dup</span>
1390
+ 160: <span class="ruby-identifier">clear</span>
1391
+ 161: <span class="ruby-ivar">@scripts</span> = <span class="ruby-identifier">scripts</span>.<span class="ruby-identifier">map</span> <span class="ruby-keyword kw">do</span> <span class="ruby-operator">|</span><span class="ruby-identifier">script</span><span class="ruby-operator">|</span>
1392
+ 162: <span class="ruby-identifier">s</span> = <span class="ruby-constant">Script</span>.<span class="ruby-identifier">new</span>(<span class="ruby-identifier">script</span>)
1393
+ 163: <span class="ruby-keyword kw">if</span> <span class="ruby-identifier">pos</span> = <span class="ruby-identifier">old</span>.<span class="ruby-identifier">index</span>(<span class="ruby-identifier">s</span>)
1394
+ 164: <span class="ruby-comment cmt"># We already got a script, so we use the old (which might got a mtime)</span>
1395
+ 165: <span class="ruby-identifier">old</span>[<span class="ruby-identifier">pos</span>]
1396
+ 166: <span class="ruby-keyword kw">else</span>
1397
+ 167: <span class="ruby-identifier">s</span>.<span class="ruby-identifier">load_apps</span>
1398
+ 168: <span class="ruby-keyword kw">end</span>
1399
+ 169: <span class="ruby-keyword kw">end</span>
1400
+ 170: <span class="ruby-keyword kw">end</span></pre>
1401
+ </div>
1402
+
1403
+ </div>
1404
+
1405
+ <h2 id="class-Camping-Reloader-App">
1406
+ <a href="#class-Camping-Reloader-App">
1407
+ Class
1408
+ Camping::Reloader::App
1409
+
1410
+ &lt;
1411
+
1412
+ (defined?(BasicObject) ? BasicObject : Object)
1413
+
1414
+
1415
+ </a>
1416
+ </h2>
1417
+
1418
+ <div class="mod">
1419
+ <p>
1420
+ This is a simple wrapper which causes the script to reload (if needed) on
1421
+ any method call. Then the method call will be forwarded to the app.
1422
+ </p>
1423
+
1424
+
1425
+ <h3>Methods</h3>
1426
+
1427
+ <h4 class="ruled" id="M000016">
1428
+ <a href="#M000016">
1429
+ Public Class method:
1430
+ <strong>::new(script)</strong>
1431
+ <img src="./images/permalink.gif">
1432
+ </a>
1433
+ </h4>
1434
+ <div class="method">
1435
+
1436
+ <p class="source-link">[ <a href="#">show source</a> ]</p>
1437
+ <pre class="sourcecode">
1438
+ <span class="ruby-comment cmt"># File lib/camping/reloader.rb, line 47</span>
1439
+ 47: <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">initialize</span>(<span class="ruby-identifier">script</span>)
1440
+ 48: <span class="ruby-ivar">@script</span> = <span class="ruby-identifier">script</span>
1441
+ 49: <span class="ruby-keyword kw">end</span></pre>
1442
+ </div>
1443
+
1444
+ <h4 class="ruled" id="M000017">
1445
+ <a href="#M000017">
1446
+ Public Instance method:
1447
+ <strong>#method_missing(meth, *args, &blk)</strong>
1448
+ <img src="./images/permalink.gif">
1449
+ </a>
1450
+ </h4>
1451
+ <div class="method">
1452
+ <p>
1453
+ Reloads if needed, before calling the method on the app.
1454
+ </p>
1455
+
1456
+ <p class="source-link">[ <a href="#">show source</a> ]</p>
1457
+ <pre class="sourcecode">
1458
+ <span class="ruby-comment cmt"># File lib/camping/reloader.rb, line 52</span>
1459
+ 52: <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">method_missing</span>(<span class="ruby-identifier">meth</span>, <span class="ruby-operator">*</span><span class="ruby-identifier">args</span>, <span class="ruby-operator">&amp;</span><span class="ruby-identifier">blk</span>)
1460
+ 53: <span class="ruby-ivar">@script</span>.<span class="ruby-identifier">reload!</span>
1461
+ 54: <span class="ruby-ivar">@app</span>.<span class="ruby-identifier">send</span>(<span class="ruby-identifier">meth</span>, <span class="ruby-operator">*</span><span class="ruby-identifier">args</span>, <span class="ruby-operator">&amp;</span><span class="ruby-identifier">blk</span>)
1462
+ 55: <span class="ruby-keyword kw">end</span></pre>
1463
+ </div>
1464
+
1465
+ </div>
1466
+
1467
+ <h2 id="class-Camping-Server">
1468
+ <a href="#class-Camping-Server">
1469
+ Class
1470
+ Camping::Server
1471
+
1472
+ &lt;
1473
+
1474
+ Object
1475
+
1476
+
1477
+ </a>
1478
+ </h2>
1479
+
1480
+ <div class="mod">
1481
+ <h3>The <a href="api.html#class-Camping">Camping</a> <a href="api.html#class-Camping-Server">Server</a> (for development)</h3>
1482
+ <p>
1483
+ <a href="api.html#class-Camping">Camping</a> includes a pretty nifty server
1484
+ which is built for development. It follows these rules:
1485
+ </p>
1486
+ <ul>
1487
+ <li>Load all <a href="api.html#class-Camping">Camping</a> apps in a directory
1488
+ or a file.
1489
+
1490
+ </li>
1491
+ <li>Load new apps that appear in that directory or that file.
1492
+
1493
+ </li>
1494
+ <li>Mount those apps according to their name. (e.g. Blog is mounted at /blog.)
1495
+
1496
+ </li>
1497
+ <li>Run each app&#8217;s <tt>create</tt> method upon startup.
1498
+
1499
+ </li>
1500
+ <li>Reload the app if its modification time changes.
1501
+
1502
+ </li>
1503
+ <li>Reload the app if it requires any files under the same directory and one of
1504
+ their modification times changes.
1505
+
1506
+ </li>
1507
+ <li>Support the X-Sendfile header.
1508
+
1509
+ </li>
1510
+ </ul>
1511
+ <p>
1512
+ Run it like this:
1513
+ </p>
1514
+ <pre>
1515
+ camping examples/ # Mounts all apps in that directory
1516
+ camping blog.rb # Mounts Blog at /
1517
+ </pre>
1518
+ <p>
1519
+ And visit <a href="http://localhost:3301">localhost:3301</a>/ in your
1520
+ browser.
1521
+ </p>
1522
+
1523
+
1524
+ <h3>Methods</h3>
1525
+
1526
+ <h4 class="ruled" id="M000032">
1527
+ <a href="#M000032">
1528
+ Public Class method:
1529
+ <strong>::new(conf, paths)</strong>
1530
+ <img src="./images/permalink.gif">
1531
+ </a>
1532
+ </h4>
1533
+ <div class="method">
1534
+
1535
+ <p class="source-link">[ <a href="#">show source</a> ]</p>
1536
+ <pre class="sourcecode">
1537
+ <span class="ruby-comment cmt"># File lib/camping/server.rb, line 29</span>
1538
+ 29: <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">initialize</span>(<span class="ruby-identifier">conf</span>, <span class="ruby-identifier">paths</span>)
1539
+ 30: <span class="ruby-ivar">@conf</span> = <span class="ruby-identifier">conf</span>
1540
+ 31: <span class="ruby-ivar">@paths</span> = <span class="ruby-identifier">paths</span>
1541
+ 32: <span class="ruby-ivar">@reloader</span> = <span class="ruby-constant">Camping</span><span class="ruby-operator">::</span><span class="ruby-constant">Reloader</span>.<span class="ruby-identifier">new</span>
1542
+ 33: <span class="ruby-identifier">connect</span>(<span class="ruby-ivar">@conf</span>.<span class="ruby-identifier">database</span>) <span class="ruby-keyword kw">if</span> <span class="ruby-ivar">@conf</span>.<span class="ruby-identifier">database</span>
1543
+ 34: <span class="ruby-keyword kw">end</span></pre>
1544
+ </div>
1545
+
1546
+ <h4 class="ruled" id="M000037">
1547
+ <a href="#M000037">
1548
+ Public Instance method:
1549
+ <strong>#app()</strong>
1550
+ <img src="./images/permalink.gif">
1551
+ </a>
1552
+ </h4>
1553
+ <div class="method">
1554
+
1555
+ <p class="source-link">[ <a href="#">show source</a> ]</p>
1556
+ <pre class="sourcecode">
1557
+ <span class="ruby-comment cmt"># File lib/camping/server.rb, line 90</span>
1558
+ 90: <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">app</span>
1559
+ 91: <span class="ruby-identifier">reload!</span>
1560
+ 92: <span class="ruby-identifier">all_apps</span> = <span class="ruby-identifier">apps</span>
1561
+ 93: <span class="ruby-identifier">rapp</span> = <span class="ruby-keyword kw">case</span> <span class="ruby-identifier">all_apps</span>.<span class="ruby-identifier">length</span>
1562
+ 94: <span class="ruby-keyword kw">when</span> <span class="ruby-value">0</span>
1563
+ 95: <span class="ruby-identifier">proc</span>{<span class="ruby-operator">|</span><span class="ruby-identifier">env</span><span class="ruby-operator">|</span>[<span class="ruby-value">200</span>,{<span class="ruby-value str">'Content-Type'</span>=<span class="ruby-operator">&gt;</span><span class="ruby-value str">'text/html'</span>},<span class="ruby-identifier">index_page</span>([])]}
1564
+ 96: <span class="ruby-keyword kw">when</span> <span class="ruby-value">1</span>
1565
+ 97: <span class="ruby-identifier">apps</span>.<span class="ruby-identifier">values</span>.<span class="ruby-identifier">first</span>
1566
+ 98: <span class="ruby-keyword kw">else</span>
1567
+ 99: <span class="ruby-identifier">hash</span> = {
1568
+ 100: <span class="ruby-value str">&quot;/&quot;</span> =<span class="ruby-operator">&gt;</span> <span class="ruby-identifier">proc</span> {<span class="ruby-operator">|</span><span class="ruby-identifier">env</span><span class="ruby-operator">|</span>[<span class="ruby-value">200</span>,{<span class="ruby-value str">'Content-Type'</span>=<span class="ruby-operator">&gt;</span><span class="ruby-value str">'text/html'</span>},<span class="ruby-identifier">index_page</span>(<span class="ruby-identifier">all_apps</span>)]}
1569
+ 101: }
1570
+ 102: <span class="ruby-identifier">all_apps</span>.<span class="ruby-identifier">each</span> <span class="ruby-keyword kw">do</span> <span class="ruby-operator">|</span><span class="ruby-identifier">mount</span>, <span class="ruby-identifier">wrapp</span><span class="ruby-operator">|</span>
1571
+ 103: <span class="ruby-comment cmt"># We're doing @reloader.reload! ourself, so we don't need the wrapper.</span>
1572
+ 104: <span class="ruby-identifier">app</span> = <span class="ruby-identifier">wrapp</span>.<span class="ruby-identifier">app</span>
1573
+ 105: <span class="ruby-identifier">hash</span>[<span class="ruby-node">&quot;/#{mount}&quot;</span>] = <span class="ruby-identifier">app</span>
1574
+ 106: <span class="ruby-identifier">hash</span>[<span class="ruby-node">&quot;/code/#{mount}&quot;</span>] = <span class="ruby-identifier">proc</span> <span class="ruby-keyword kw">do</span> <span class="ruby-operator">|</span><span class="ruby-identifier">env</span><span class="ruby-operator">|</span>
1575
+ 107: [<span class="ruby-value">200</span>,{<span class="ruby-value str">'Content-Type'</span>=<span class="ruby-operator">&gt;</span><span class="ruby-value str">'text/plain'</span>,<span class="ruby-value str">'X-Sendfile'</span>=<span class="ruby-operator">&gt;</span><span class="ruby-identifier">wrapp</span>.<span class="ruby-identifier">script</span>.<span class="ruby-identifier">file</span>},<span class="ruby-value str">''</span>]
1576
+ 108: <span class="ruby-keyword kw">end</span>
1577
+ 109: <span class="ruby-keyword kw">end</span>
1578
+ 110: <span class="ruby-constant">Rack</span><span class="ruby-operator">::</span><span class="ruby-constant">URLMap</span>.<span class="ruby-identifier">new</span>(<span class="ruby-identifier">hash</span>)
1579
+ 111: <span class="ruby-keyword kw">end</span>
1580
+ 112: <span class="ruby-identifier">rapp</span> = <span class="ruby-constant">Rack</span><span class="ruby-operator">::</span><span class="ruby-constant">ContentLength</span>.<span class="ruby-identifier">new</span>(<span class="ruby-identifier">rapp</span>)
1581
+ 113: <span class="ruby-identifier">rapp</span> = <span class="ruby-constant">Rack</span><span class="ruby-operator">::</span><span class="ruby-constant">Lint</span>.<span class="ruby-identifier">new</span>(<span class="ruby-identifier">rapp</span>)
1582
+ 114: <span class="ruby-identifier">rapp</span> = <span class="ruby-constant">XSendfile</span>.<span class="ruby-identifier">new</span>(<span class="ruby-identifier">rapp</span>)
1583
+ 115: <span class="ruby-identifier">rapp</span> = <span class="ruby-constant">Rack</span><span class="ruby-operator">::</span><span class="ruby-constant">ShowExceptions</span>.<span class="ruby-identifier">new</span>(<span class="ruby-identifier">rapp</span>)
1584
+ 116: <span class="ruby-keyword kw">end</span></pre>
1585
+ </div>
1586
+
1587
+ <h4 class="ruled" id="M000038">
1588
+ <a href="#M000038">
1589
+ Public Instance method:
1590
+ <strong>#apps()</strong>
1591
+ <img src="./images/permalink.gif">
1592
+ </a>
1593
+ </h4>
1594
+ <div class="method">
1595
+
1596
+ <p class="source-link">[ <a href="#">show source</a> ]</p>
1597
+ <pre class="sourcecode">
1598
+ <span class="ruby-comment cmt"># File lib/camping/server.rb, line 118</span>
1599
+ 118: <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">apps</span>
1600
+ 119: <span class="ruby-ivar">@reloader</span>.<span class="ruby-identifier">apps</span>.<span class="ruby-identifier">inject</span>({}) <span class="ruby-keyword kw">do</span> <span class="ruby-operator">|</span><span class="ruby-identifier">h</span>, (<span class="ruby-identifier">mount</span>, <span class="ruby-identifier">wrapp</span>)<span class="ruby-operator">|</span>
1601
+ 120: <span class="ruby-identifier">h</span>[<span class="ruby-identifier">mount</span>.<span class="ruby-identifier">to_s</span>.<span class="ruby-identifier">downcase</span>] = <span class="ruby-identifier">wrapp</span>
1602
+ 121: <span class="ruby-identifier">h</span>
1603
+ 122: <span class="ruby-keyword kw">end</span>
1604
+ 123: <span class="ruby-keyword kw">end</span></pre>
1605
+ </div>
1606
+
1607
+ <h4 class="ruled" id="M000039">
1608
+ <a href="#M000039">
1609
+ Public Instance method:
1610
+ <strong>#call(env)</strong>
1611
+ <img src="./images/permalink.gif">
1612
+ </a>
1613
+ </h4>
1614
+ <div class="method">
1615
+
1616
+ <p class="source-link">[ <a href="#">show source</a> ]</p>
1617
+ <pre class="sourcecode">
1618
+ <span class="ruby-comment cmt"># File lib/camping/server.rb, line 125</span>
1619
+ 125: <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">call</span>(<span class="ruby-identifier">env</span>)
1620
+ 126: <span class="ruby-identifier">app</span>.<span class="ruby-identifier">call</span>(<span class="ruby-identifier">env</span>)
1621
+ 127: <span class="ruby-keyword kw">end</span></pre>
1622
+ </div>
1623
+
1624
+ <h4 class="ruled" id="M000033">
1625
+ <a href="#M000033">
1626
+ Public Instance method:
1627
+ <strong>#connect(db)</strong>
1628
+ <img src="./images/permalink.gif">
1629
+ </a>
1630
+ </h4>
1631
+ <div class="method">
1632
+
1633
+ <p class="source-link">[ <a href="#">show source</a> ]</p>
1634
+ <pre class="sourcecode">
1635
+ <span class="ruby-comment cmt"># File lib/camping/server.rb, line 36</span>
1636
+ 36: <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">connect</span>(<span class="ruby-identifier">db</span>)
1637
+ 37: <span class="ruby-keyword kw">unless</span> <span class="ruby-constant">Camping</span>.<span class="ruby-identifier">autoload?</span>(<span class="ruby-identifier">:Models</span>)
1638
+ 38: <span class="ruby-constant">Camping</span><span class="ruby-operator">::</span><span class="ruby-constant">Models</span><span class="ruby-operator">::</span><span class="ruby-constant">Base</span>.<span class="ruby-identifier">establish_connection</span>(<span class="ruby-identifier">db</span>)
1639
+ 39: <span class="ruby-keyword kw">end</span>
1640
+ 40: <span class="ruby-keyword kw">end</span></pre>
1641
+ </div>
1642
+
1643
+ <h4 class="ruled" id="M000035">
1644
+ <a href="#M000035">
1645
+ Public Instance method:
1646
+ <strong>#find_scripts()</strong>
1647
+ <img src="./images/permalink.gif">
1648
+ </a>
1649
+ </h4>
1650
+ <div class="method">
1651
+
1652
+ <p class="source-link">[ <a href="#">show source</a> ]</p>
1653
+ <pre class="sourcecode">
1654
+ <span class="ruby-comment cmt"># File lib/camping/server.rb, line 42</span>
1655
+ 42: <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">find_scripts</span>
1656
+ 43: <span class="ruby-identifier">scripts</span> = <span class="ruby-ivar">@paths</span>.<span class="ruby-identifier">map</span> <span class="ruby-keyword kw">do</span> <span class="ruby-operator">|</span><span class="ruby-identifier">path</span><span class="ruby-operator">|</span>
1657
+ 44: <span class="ruby-keyword kw">case</span>
1658
+ 45: <span class="ruby-keyword kw">when</span> <span class="ruby-constant">File</span>.<span class="ruby-identifier">file?</span>(<span class="ruby-identifier">path</span>)
1659
+ 46: <span class="ruby-identifier">path</span>
1660
+ 47: <span class="ruby-keyword kw">when</span> <span class="ruby-constant">File</span>.<span class="ruby-identifier">directory?</span>(<span class="ruby-identifier">path</span>)
1661
+ 48: <span class="ruby-constant">Dir</span>[<span class="ruby-constant">File</span>.<span class="ruby-identifier">join</span>(<span class="ruby-identifier">path</span>, <span class="ruby-value str">'*.rb'</span>)]
1662
+ 49: <span class="ruby-keyword kw">end</span>
1663
+ 50: <span class="ruby-keyword kw">end</span>.<span class="ruby-identifier">flatten</span>.<span class="ruby-identifier">compact</span>
1664
+ 51: <span class="ruby-ivar">@reloader</span>.<span class="ruby-identifier">update</span>(<span class="ruby-operator">*</span><span class="ruby-identifier">scripts</span>)
1665
+ 52: <span class="ruby-keyword kw">end</span></pre>
1666
+ </div>
1667
+
1668
+ <h4 class="ruled" id="M000036">
1669
+ <a href="#M000036">
1670
+ Public Instance method:
1671
+ <strong>#index_page(apps)</strong>
1672
+ <img src="./images/permalink.gif">
1673
+ </a>
1674
+ </h4>
1675
+ <div class="method">
1676
+
1677
+ <p class="source-link">[ <a href="#">show source</a> ]</p>
1678
+ <pre class="sourcecode">
1679
+ <span class="ruby-comment cmt"># File lib/camping/server.rb, line 54</span>
1680
+ 54: <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">index_page</span>(<span class="ruby-identifier">apps</span>)
1681
+ 55: <span class="ruby-identifier">welcome</span> = <span class="ruby-value str">&quot;You are Camping&quot;</span>
1682
+ 56: <span class="ruby-identifier">header</span> = <span class="ruby-value str">&quot;&lt;html&gt;\n&lt;head&gt;\n&lt;title&gt;\#{welcome}&lt;/title&gt;\n&lt;style type=\&quot;text/css\&quot;&gt;\nbody {\nfont-family: verdana, arial, sans-serif;\npadding: 10px 40px;\nmargin: 0;\n}\nh1, h2, h3, h4, h5, h6 {\nfont-family: utopia, georgia, serif;\n}\n&lt;/style&gt;\n&lt;/head&gt;\n&lt;body&gt;\n&lt;h1&gt;\#{welcome}&lt;/h1&gt;\n&quot;</span>
1683
+ 57: <span class="ruby-identifier">footer</span> = <span class="ruby-value str">'&lt;/body&gt;&lt;/html&gt;'</span>
1684
+ 58: <span class="ruby-identifier">main</span> = <span class="ruby-keyword kw">if</span> <span class="ruby-identifier">apps</span>.<span class="ruby-identifier">empty?</span>
1685
+ 59: <span class="ruby-value str">&quot;&lt;p&gt;Good day. I'm sorry, but I could not find any Camping apps. &quot;</span>\
1686
+ 60: <span class="ruby-value str">&quot;You might want to take a look at the console to see if any errors &quot;</span>\
1687
+ 61: <span class="ruby-value str">&quot;have been raised.&lt;/p&gt;&quot;</span>
1688
+ 62: <span class="ruby-keyword kw">else</span>
1689
+ 63: <span class="ruby-value str">&quot;&lt;p&gt;Good day. These are the Camping apps you've mounted.&lt;/p&gt;&lt;ul&gt;&quot;</span> <span class="ruby-operator">+</span>
1690
+ 64: <span class="ruby-identifier">apps</span>.<span class="ruby-identifier">map</span> <span class="ruby-keyword kw">do</span> <span class="ruby-operator">|</span><span class="ruby-identifier">mount</span>, <span class="ruby-identifier">app</span><span class="ruby-operator">|</span>
1691
+ 65: <span class="ruby-node">&quot;&lt;li&gt;&lt;h3 style=\&quot;display: inline\&quot;&gt;&lt;a href=\&quot;/#{mount}\&quot;&gt;#{app}&lt;/a&gt;&lt;/h3&gt;&lt;small&gt; / &lt;a href=\&quot;/code/#{mount}\&quot;&gt;View source&lt;/a&gt;&lt;/small&gt;&lt;/li&gt;&quot;</span>
1692
+ 66: <span class="ruby-keyword kw">end</span>.<span class="ruby-identifier">join</span>(<span class="ruby-value str">&quot;\n&quot;</span>) <span class="ruby-operator">+</span> <span class="ruby-value str">'&lt;/ul&gt;'</span>
1693
+ 67: <span class="ruby-keyword kw">end</span>
1694
+ 68:
1695
+ 69: <span class="ruby-identifier">header</span> <span class="ruby-operator">+</span> <span class="ruby-identifier">main</span> <span class="ruby-operator">+</span> <span class="ruby-identifier">footer</span>
1696
+ 70: <span class="ruby-keyword kw">end</span></pre>
1697
+ </div>
1698
+
1699
+ <h4 class="ruled" id="M000041">
1700
+ <a href="#M000041">
1701
+ Public Instance method:
1702
+ <strong>#reload!()</strong>
1703
+ <img src="./images/permalink.gif">
1704
+ </a>
1705
+ </h4>
1706
+ <div class="method">
1707
+
1708
+ <p class="source-link">[ <a href="#">show source</a> ]</p>
1709
+ <pre class="sourcecode">
1710
+ <span class="ruby-comment cmt"># File lib/camping/server.rb, line 149</span>
1711
+ 149: <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">reload!</span>
1712
+ 150: <span class="ruby-identifier">find_scripts</span>
1713
+ 151: <span class="ruby-ivar">@reloader</span>.<span class="ruby-identifier">reload!</span>
1714
+ 152: <span class="ruby-keyword kw">end</span></pre>
1715
+ </div>
1716
+
1717
+ <h4 class="ruled" id="M000040">
1718
+ <a href="#M000040">
1719
+ Public Instance method:
1720
+ <strong>#start()</strong>
1721
+ <img src="./images/permalink.gif">
1722
+ </a>
1723
+ </h4>
1724
+ <div class="method">
1725
+
1726
+ <p class="source-link">[ <a href="#">show source</a> ]</p>
1727
+ <pre class="sourcecode">
1728
+ <span class="ruby-comment cmt"># File lib/camping/server.rb, line 129</span>
1729
+ 129: <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">start</span>
1730
+ 130: <span class="ruby-identifier">handler</span>, <span class="ruby-identifier">conf</span> = <span class="ruby-keyword kw">case</span> <span class="ruby-ivar">@conf</span>.<span class="ruby-identifier">server</span>
1731
+ 131: <span class="ruby-keyword kw">when</span> <span class="ruby-value str">&quot;console&quot;</span>
1732
+ 132: <span class="ruby-identifier">puts</span> <span class="ruby-value str">&quot;** Starting console&quot;</span>
1733
+ 133: <span class="ruby-identifier">reload!</span>
1734
+ 134: <span class="ruby-identifier">this</span> = <span class="ruby-keyword kw">self</span>; <span class="ruby-identifier">eval</span>(<span class="ruby-value str">&quot;self&quot;</span>, <span class="ruby-constant">TOPLEVEL_BINDING</span>).<span class="ruby-identifier">meta_def</span>(<span class="ruby-identifier">:reload!</span>) { <span class="ruby-identifier">this</span>.<span class="ruby-identifier">reload!</span>; <span class="ruby-keyword kw">nil</span> }
1735
+ 135: <span class="ruby-constant">ARGV</span>.<span class="ruby-identifier">clear</span>
1736
+ 136: <span class="ruby-constant">IRB</span>.<span class="ruby-identifier">start</span>
1737
+ 137: <span class="ruby-identifier">exit</span>
1738
+ 138: <span class="ruby-keyword kw">when</span> <span class="ruby-value str">&quot;mongrel&quot;</span>
1739
+ 139: <span class="ruby-identifier">puts</span> <span class="ruby-node">&quot;** Starting Mongrel on #{@conf.host}:#{@conf.port}&quot;</span>
1740
+ 140: [<span class="ruby-constant">Rack</span><span class="ruby-operator">::</span><span class="ruby-constant">Handler</span><span class="ruby-operator">::</span><span class="ruby-constant">Mongrel</span>, {<span class="ruby-identifier">:Port</span> =<span class="ruby-operator">&gt;</span> <span class="ruby-ivar">@conf</span>.<span class="ruby-identifier">port</span>, <span class="ruby-identifier">:Host</span> =<span class="ruby-operator">&gt;</span> <span class="ruby-ivar">@conf</span>.<span class="ruby-identifier">host</span>}]
1741
+ 141: <span class="ruby-keyword kw">when</span> <span class="ruby-value str">&quot;webrick&quot;</span>
1742
+ 142: <span class="ruby-identifier">puts</span> <span class="ruby-node">&quot;** Starting WEBrick on #{@conf.host}:#{@conf.port}&quot;</span>
1743
+ 143: [<span class="ruby-constant">Rack</span><span class="ruby-operator">::</span><span class="ruby-constant">Handler</span><span class="ruby-operator">::</span><span class="ruby-constant">WEBrick</span>, {<span class="ruby-identifier">:Port</span> =<span class="ruby-operator">&gt;</span> <span class="ruby-ivar">@conf</span>.<span class="ruby-identifier">port</span>, <span class="ruby-identifier">:BindAddress</span> =<span class="ruby-operator">&gt;</span> <span class="ruby-ivar">@conf</span>.<span class="ruby-identifier">host</span>}]
1744
+ 144: <span class="ruby-keyword kw">end</span>
1745
+ 145: <span class="ruby-identifier">reload!</span>
1746
+ 146: <span class="ruby-identifier">handler</span>.<span class="ruby-identifier">run</span>(<span class="ruby-keyword kw">self</span>, <span class="ruby-identifier">conf</span>)
1747
+ 147: <span class="ruby-keyword kw">end</span></pre>
1748
+ </div>
1749
+
1750
+ </div>
1751
+
1752
+ <h2 id="class-Camping-Server-XSendfile">
1753
+ <a href="#class-Camping-Server-XSendfile">
1754
+ Class
1755
+ Camping::Server::XSendfile
1756
+
1757
+ &lt;
1758
+
1759
+ Object
1760
+
1761
+
1762
+ </a>
1763
+ </h2>
1764
+
1765
+ <div class="mod">
1766
+ <p>
1767
+ A Rack middleware for reading X-Sendfile. Should only be used in
1768
+ development.
1769
+ </p>
1770
+
1771
+
1772
+ <h3>Methods</h3>
1773
+
1774
+ <h4 class="ruled" id="M000042">
1775
+ <a href="#M000042">
1776
+ Public Class method:
1777
+ <strong>::new(app)</strong>
1778
+ <img src="./images/permalink.gif">
1779
+ </a>
1780
+ </h4>
1781
+ <div class="method">
1782
+
1783
+ <p class="source-link">[ <a href="#">show source</a> ]</p>
1784
+ <pre class="sourcecode">
1785
+ <span class="ruby-comment cmt"># File lib/camping/server.rb, line 164</span>
1786
+ 164: <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">initialize</span>(<span class="ruby-identifier">app</span>)
1787
+ 165: <span class="ruby-ivar">@app</span> = <span class="ruby-identifier">app</span>
1788
+ 166: <span class="ruby-keyword kw">end</span></pre>
1789
+ </div>
1790
+
1791
+ <h4 class="ruled" id="M000043">
1792
+ <a href="#M000043">
1793
+ Public Instance method:
1794
+ <strong>#call(env)</strong>
1795
+ <img src="./images/permalink.gif">
1796
+ </a>
1797
+ </h4>
1798
+ <div class="method">
1799
+
1800
+ <p class="source-link">[ <a href="#">show source</a> ]</p>
1801
+ <pre class="sourcecode">
1802
+ <span class="ruby-comment cmt"># File lib/camping/server.rb, line 168</span>
1803
+ 168: <span class="ruby-keyword kw">def</span> <span class="ruby-identifier">call</span>(<span class="ruby-identifier">env</span>)
1804
+ 169: <span class="ruby-identifier">status</span>, <span class="ruby-identifier">headers</span>, <span class="ruby-identifier">body</span> = <span class="ruby-ivar">@app</span>.<span class="ruby-identifier">call</span>(<span class="ruby-identifier">env</span>)
1805
+ 170: <span class="ruby-identifier">headers</span> = <span class="ruby-constant">Rack</span><span class="ruby-operator">::</span><span class="ruby-constant">Utils</span><span class="ruby-operator">::</span><span class="ruby-constant">HeaderHash</span>.<span class="ruby-identifier">new</span>(<span class="ruby-identifier">headers</span>)
1806
+ 171: <span class="ruby-keyword kw">if</span> <span class="ruby-identifier">header</span> = <span class="ruby-constant">HEADERS</span>.<span class="ruby-identifier">detect</span> { <span class="ruby-operator">|</span><span class="ruby-identifier">header</span><span class="ruby-operator">|</span> <span class="ruby-identifier">headers</span>.<span class="ruby-identifier">include?</span>(<span class="ruby-identifier">header</span>) }
1807
+ 172: <span class="ruby-identifier">path</span> = <span class="ruby-identifier">headers</span>[<span class="ruby-identifier">header</span>]
1808
+ 173: <span class="ruby-identifier">body</span> = <span class="ruby-constant">File</span>.<span class="ruby-identifier">read</span>(<span class="ruby-identifier">path</span>)
1809
+ 174: <span class="ruby-identifier">headers</span>[<span class="ruby-value str">'Content-Length'</span>] = <span class="ruby-identifier">body</span>.<span class="ruby-identifier">length</span>.<span class="ruby-identifier">to_s</span>
1810
+ 175: <span class="ruby-keyword kw">end</span>
1811
+ 176: [<span class="ruby-identifier">status</span>, <span class="ruby-identifier">headers</span>, <span class="ruby-identifier">body</span>]
1812
+ 177: <span class="ruby-keyword kw">end</span></pre>
1813
+ </div>
1814
+
1815
+ </div>
1816
+
1817
+ <h2 id="class-Camping-Session">
1818
+ <a href="#class-Camping-Session">
1819
+ Module
1820
+ Camping::Session
1821
+
1822
+ </a>
1823
+ </h2>
1824
+
1825
+ <div class="mod">
1826
+ <h3>Getting Started</h3>
1827
+ <p>
1828
+ To get sessions working for your application:
1829
+ </p>
1830
+ <ol>
1831
+ <li><tt>require 'camping/session'</tt>
1832
+
1833
+ </li>
1834
+ <li>Mixin the module: <tt>include Camping::Session</tt>
1835
+
1836
+ </li>
1837
+ <li>Define a secret (and keep it secret): <tt>secret &quot;SECRET!&quot;</tt>
1838
+
1839
+ </li>
1840
+ <li>Throughout your application, use the <tt>@state</tt> var like a hash to
1841
+ store your application&#8217;s data.
1842
+
1843
+ </li>
1844
+ </ol>
1845
+ <pre>
1846
+ require 'camping/session' # 1
1847
+
1848
+ module Nuts
1849
+ include Camping::Session # 2
1850
+ secret &quot;Oh yeah!&quot; # 3
1851
+ end
1852
+ </pre>
1853
+ <h3>Other backends</h3>
1854
+ <p>
1855
+ <a href="api.html#class-Camping">Camping</a> only ships with
1856
+ session-cookies. However, the <tt>@state</tt> variable is simply a shortcut
1857
+ for <tt>@<a href="http://'rack.session'">env</a></tt>. Therefore you can
1858
+ also use any middleware which sets this variable:
1859
+ </p>
1860
+ <pre>
1861
+ module Nuts
1862
+ use Rack::Session::Memcache
1863
+ end
1864
+ </pre>
1865
+
1866
+
1867
+ <h3>Methods</h3>
1868
+
1869
+ <h4 class="ruled" id="M000034">
1870
+ <a href="#M000034">
1871
+ Public Class method:
1872
+ <strong>::included(app)</strong>
1873
+ <img src="./images/permalink.gif">
1874
+ </a>
1875
+ </h4>
1876
+ <div class="method">
1877
+
1878
+ <p class="source-link">[ <a href="#">show source</a> ]</p>
1879
+ <pre class="sourcecode">
1880
+ <span class="ruby-comment cmt"># File lib/camping/session.rb, line 28</span>
1881
+ 28: <span class="ruby-keyword kw">def</span> <span class="ruby-keyword kw">self</span>.<span class="ruby-identifier">included</span>(<span class="ruby-identifier">app</span>)
1882
+ 29: <span class="ruby-identifier">key</span> = <span class="ruby-node">&quot;#{app}.state&quot;</span>.<span class="ruby-identifier">downcase</span>
1883
+ 30: <span class="ruby-identifier">secret</span> = [<span class="ruby-keyword kw">__FILE__</span>, <span class="ruby-constant">File</span>.<span class="ruby-identifier">mtime</span>(<span class="ruby-keyword kw">__FILE__</span>)].<span class="ruby-identifier">join</span>(<span class="ruby-value str">&quot;:&quot;</span>)
1884
+ 31:
1885
+ 32: <span class="ruby-identifier">app</span>.<span class="ruby-identifier">meta_def</span>(<span class="ruby-identifier">:secret</span>) { <span class="ruby-operator">|</span><span class="ruby-identifier">val</span><span class="ruby-operator">|</span> <span class="ruby-identifier">secret</span>.<span class="ruby-identifier">replace</span>(<span class="ruby-identifier">val</span>) }
1886
+ 33: <span class="ruby-identifier">app</span>.<span class="ruby-identifier">use</span> <span class="ruby-constant">Rack</span><span class="ruby-operator">::</span><span class="ruby-constant">Session</span><span class="ruby-operator">::</span><span class="ruby-constant">Cookie</span>, <span class="ruby-identifier">:key</span> =<span class="ruby-operator">&gt;</span> <span class="ruby-identifier">key</span>, <span class="ruby-identifier">:secret</span> =<span class="ruby-operator">&gt;</span> <span class="ruby-identifier">secret</span>
1887
+ 34: <span class="ruby-keyword kw">end</span></pre>
1888
+ </div>
1889
+
1890
+ </div>
1891
+
1892
+ <h2 id="class-Camping-Views">
1893
+ <a href="#class-Camping-Views">
1894
+ Module
1895
+ Camping::Views
1896
+
1897
+ </a>
1898
+ </h2>
1899
+
1900
+ <div class="mod">
1901
+ <p>
1902
+ <a href="api.html#class-Camping-Views">Views</a> is an empty module for
1903
+ storing methods which create HTML. The HTML is described using the Markaby
1904
+ language.
1905
+ </p>
1906
+ <h3>Defining and calling templates</h3>
1907
+ <p>
1908
+ Templates are simply Ruby methods with Markaby inside:
1909
+ </p>
1910
+ <pre>
1911
+ module Blog::Views
1912
+ def index
1913
+ p &quot;Welcome to my blog&quot;
1914
+ end
1915
+
1916
+ def show
1917
+ h1 @post.title
1918
+ self &lt;&lt; @post.content
1919
+ end
1920
+ end
1921
+ </pre>
1922
+ <p>
1923
+ In your controllers you just call <tt>render :template_name</tt> which will
1924
+ invoke the template. The views and controllers will share instance
1925
+ variables (as you can see above).
1926
+ </p>
1927
+ <h3>Using the layout method</h3>
1928
+ <p>
1929
+ If your <a href="api.html#class-Camping-Views">Views</a> module has a
1930
+ <tt>layout</tt> method defined, it will be called with a block which will
1931
+ insert content from your view:
1932
+ </p>
1933
+ <pre>
1934
+ module Blog::Views
1935
+ def layout
1936
+ html do
1937
+ head { title &quot;My Blog &quot;}
1938
+ body { self &lt;&lt; yield }
1939
+ end
1940
+ end
1941
+ end
1942
+ </pre>
1943
+
1944
+
1945
+ <h3>Methods</h3>
1946
+
1947
+ </div>
1948
+
1949
+ </div>
1950
+ </div>
1951
+ </div>
1952
+ </body>
1953
+ </html>