picnic 0.8.0 → 0.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. data/History.txt +10 -0
  2. data/Manifest.txt +27 -27
  3. data/lib/picnic.rb +1 -1
  4. data/lib/picnic/cli.rb +2 -0
  5. data/lib/picnic/conf.rb +30 -6
  6. data/lib/picnic/server.rb +18 -21
  7. data/lib/picnic/version.rb +1 -1
  8. data/picnic.gemspec +3 -3
  9. data/vendor/{camping-2.0.20090212 → zuk-camping-2.0.20090429}/CHANGELOG +0 -0
  10. data/vendor/{camping-2.0.20090212 → zuk-camping-2.0.20090429}/COPYING +0 -0
  11. data/vendor/zuk-camping-2.0.20090429/README +82 -0
  12. data/vendor/{camping-2.0.20090212 → zuk-camping-2.0.20090429}/Rakefile +9 -3
  13. data/vendor/zuk-camping-2.0.20090429/bin/camping +97 -0
  14. data/vendor/{camping-2.0.20090212 → zuk-camping-2.0.20090429}/doc/camping.1.gz +0 -0
  15. data/vendor/{camping-2.0.20090212 → zuk-camping-2.0.20090429}/examples/README +0 -0
  16. data/vendor/{camping-2.0.20090212 → zuk-camping-2.0.20090429}/examples/blog.rb +0 -0
  17. data/vendor/{camping-2.0.20090212 → zuk-camping-2.0.20090429}/examples/campsh.rb +0 -0
  18. data/vendor/{camping-2.0.20090212 → zuk-camping-2.0.20090429}/examples/tepee.rb +0 -0
  19. data/vendor/{camping-2.0.20090212 → zuk-camping-2.0.20090429}/extras/Camping.gif +0 -0
  20. data/vendor/zuk-camping-2.0.20090429/extras/flipbook.rb +357 -0
  21. data/vendor/{camping-2.0.20090212 → zuk-camping-2.0.20090429}/extras/permalink.gif +0 -0
  22. data/vendor/{camping-2.0.20090212 → zuk-camping-2.0.20090429}/lib/camping-unabridged.rb +53 -61
  23. data/vendor/{camping-2.0.20090212 → zuk-camping-2.0.20090429}/lib/camping.rb +23 -25
  24. data/vendor/{camping-2.0.20090212 → zuk-camping-2.0.20090429}/lib/camping/ar.rb +0 -0
  25. data/vendor/{camping-2.0.20090212 → zuk-camping-2.0.20090429}/lib/camping/ar/session.rb +0 -0
  26. data/vendor/{camping-2.0.20090212 → zuk-camping-2.0.20090429}/lib/camping/mab.rb +0 -0
  27. data/vendor/zuk-camping-2.0.20090429/lib/camping/reloader.rb +188 -0
  28. data/vendor/zuk-camping-2.0.20090429/lib/camping/server.rb +159 -0
  29. data/vendor/{camping-2.0.20090212 → zuk-camping-2.0.20090429}/lib/camping/session.rb +1 -0
  30. data/vendor/{camping-2.0.20090212 → zuk-camping-2.0.20090429}/setup.rb +0 -0
  31. data/vendor/{camping-2.0.20090212 → zuk-camping-2.0.20090429}/test/apps/env_debug.rb +0 -0
  32. data/vendor/{camping-2.0.20090212 → zuk-camping-2.0.20090429}/test/apps/forms.rb +0 -0
  33. data/vendor/{camping-2.0.20090212 → zuk-camping-2.0.20090429}/test/apps/misc.rb +0 -0
  34. data/vendor/{camping-2.0.20090212 → zuk-camping-2.0.20090429}/test/apps/sessions.rb +0 -0
  35. data/vendor/{camping-2.0.20090212 → zuk-camping-2.0.20090429}/test/test_camping.rb +0 -0
  36. metadata +29 -29
  37. data/vendor/camping-2.0.20090212/README +0 -119
  38. data/vendor/camping-2.0.20090212/bin/camping +0 -99
  39. data/vendor/camping-2.0.20090212/extras/flipbook_rdoc.rb +0 -491
  40. data/vendor/camping-2.0.20090212/lib/camping/reloader.rb +0 -163
  41. data/vendor/camping-2.0.20090212/lib/camping/server.rb +0 -158
@@ -0,0 +1,357 @@
1
+ CAMPING_EXTRAS_DIR = File.expand_path(File.dirname(__FILE__))
2
+ require 'rdoc/generator/html'
3
+
4
+ module RDoc::Generator
5
+ [Class, File].each do |klass|
6
+ old = klass.instance_method(:value_hash)
7
+ klass.send(:define_method, :value_hash) {
8
+ old.bind(self).call
9
+ @values['root'] = @path.split("/").map { ".." }[1..-1].join("/")
10
+ @values
11
+ }
12
+ end
13
+
14
+ module HTML::FLIPBOOK
15
+ ######################################################################
16
+ #
17
+ # The following is used for the -1 option
18
+ #
19
+
20
+ FONTS = "verdana,arial,'Bitstream Vera Sans',helvetica,sans-serif"
21
+
22
+ STYLE = %{
23
+ body, th, td {
24
+ font: normal 14px verdana,arial,'Bitstream Vera Sans',helvetica,sans-serif;
25
+ line-height: 160%;
26
+ padding: 0; margin: 0;
27
+ margin-bottom: 30px;
28
+ /* background-color: #402; */
29
+ background-color: #694;
30
+ }
31
+ h1, h2, h3, h4 {
32
+ font-family: Utopia, Georgia, serif;
33
+ font-weight: bold;
34
+ letter-spacing: -0.018em;
35
+ }
36
+ h1 { font-size: 24px; margin: .15em 1em 0 0 }
37
+ h2 { font-size: 24px }
38
+ h3 { font-size: 19px }
39
+ h4 { font-size: 17px; font-weight: normal; }
40
+ h4.ruled { border-bottom: solid 1px #CC9; }
41
+ h2.ruled { padding-top: 35px; border-top: solid 1px #AA5; }
42
+
43
+ /* Link styles */
44
+ :link, :visited {
45
+ color: #00b;
46
+ }
47
+ :link:hover, :visited:hover {
48
+ background-color: #eee;
49
+ color: #B22;
50
+ }
51
+ #fullpage {
52
+ width: 720px;
53
+ margin: 0 auto;
54
+ }
55
+ .page_shade, .page {
56
+ padding: 0px 5px 5px 0px;
57
+ background-color: #fcfcf9;
58
+ border: solid 1px #983;
59
+ }
60
+ .page {
61
+ margin-left: -5px;
62
+ margin-top: -5px;
63
+ padding: 20px 35px;
64
+ }
65
+ .page .header {
66
+ float: right;
67
+ color: #777;
68
+ font-size: 10px;
69
+ }
70
+ .page h1, .page h2, .page h3 {
71
+ clear: both;
72
+ text-align: center;
73
+ }
74
+ #pager {
75
+ padding: 10px 4px;
76
+ color: white;
77
+ font-size: 11px;
78
+ }
79
+ #pager :link, #pager :visited {
80
+ color: #bfb;
81
+ padding: 0px 5px;
82
+ }
83
+ #pager :link:hover, #pager :visited:hover {
84
+ background-color: #262;
85
+ color: white;
86
+ }
87
+ #logo { float: left; }
88
+ #menu { background-color: #dfa; padding: 4px 12px; margin: 0; }
89
+ #menu h3 { padding: 0; margin: 0; }
90
+ #menu #links { float: right; }
91
+ pre { font-weight: bold; color: #730; }
92
+ tt { color: #703; font-size: 12pt; }
93
+ .dyn-source { background-color: #775915; padding: 4px 8px; margin: 0; display: none; }
94
+ .dyn-source pre { color: #DDDDDD; font-size: 8pt; }
95
+ .source-link { text-align: right; font-size: 8pt; }
96
+ .ruby-comment { color: green; font-style: italic }
97
+ .ruby-constant { color: #CCDDFF; font-weight: bold; }
98
+ .ruby-identifier { color: #CCCCCC; }
99
+ .ruby-ivar { color: #BBCCFF; }
100
+ .ruby-keyword { color: #EEEEFF; font-weight: bold }
101
+ .ruby-node { color: #FFFFFF; }
102
+ .ruby-operator { color: #CCCCCC; }
103
+ .ruby-regexp { color: #DDFFDD; }
104
+ .ruby-value { color: #FFAAAA; font-style: italic }
105
+ .kw { color: #DDDDFF; font-weight: bold }
106
+ .cmt { color: #CCFFCC; font-style: italic }
107
+ .str { color: #EECCCC; font-style: italic }
108
+ .re { color: #EECCCC; }
109
+ }
110
+
111
+ CONTENTS_XML = %q{
112
+ <%= values['description'] if values['description'] %>
113
+
114
+ <% if values['requires'] %>
115
+ <h4>Requires:</h4>
116
+ <ul>
117
+ <% values['requires'].each do |req| %>
118
+ <li><%= href(req['aref'], req['name']) %></li>
119
+ <% end %>
120
+ <% end %>
121
+
122
+ <% if values['attributes'] %>
123
+ <h4>Attributes</h4>
124
+ <table>
125
+ <% values['attribtes'].each do |attr| %>
126
+ <tr><td><%= attr['name'] %></td><td><%= attr['rw'] %></td><td><%= attr['a_desc'] %></td></tr>
127
+ <% end %>
128
+ </table>
129
+ <% end %>
130
+
131
+ <% if values['includes'] %>
132
+ <h4>Includes</h4>
133
+ <ul>
134
+ <% values['includes'].each do |i| %>
135
+ <li><%= href i['aref'], i['name'] %></li>
136
+ <% end %>
137
+ </ul>
138
+ <% end %>
139
+
140
+ <% values['sections'].each do |sec| %>
141
+ <% if sec['method_list'] %>
142
+ <h2 class="ruled">Methods</h2>
143
+ <% sec['method_list'].each do |ml| %>
144
+ <% if ml['methods'] %>
145
+ <% ml['methods'].each do |m| %>
146
+ <h4 class="ruled"><%= m['type'] %> <%= m['category'] %> method:
147
+ <% c = m['callseq'] %>
148
+ <strong id="<%= m['aref'] %>"><%= c ? c : m['name'] + m['params'] %></strong>
149
+ <a href="#<%= m['aref'] %>"><img src="<%= values['root'] %>/permalink.gif" border="0" title="Permalink to <%= c ? c : "#{m['type']} #{m['category']} method: #{m['name']}" %>" /></a></h4>
150
+
151
+ <%= m['m_desc'] if m['m_desc'] %>
152
+
153
+ <% if m['sourcecode'] %>
154
+ <div class="sourcecode">
155
+ <p class="source-link">[ <a href="javascript:toggleSource('<%= m['aref'] %>_source')" id="l_<%= m['aref'] %>_source">show source</a> ]</p>
156
+ <div id="<%= m['aref'] %>_source" class="dyn-source">
157
+ <pre>
158
+ <%= m['sourcecode'] %>
159
+ </pre>
160
+ </div>
161
+ </div>
162
+ <% end %>
163
+ <% end %>
164
+ <% end %>
165
+ <% end %>
166
+ <% end %>
167
+ <% end %>
168
+ }
169
+
170
+ ############################################################################
171
+
172
+
173
+ BODY = %q{
174
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
175
+ <html>
176
+ <head>
177
+ <title>
178
+ <% if values['title'] %>
179
+ <%= values['realtitle'] %> &raquo; <%= values['title'] %>
180
+ <% else %>
181
+ <%= values['realtitle'] %>
182
+ <% end %>
183
+ </title>
184
+ <meta http-equiv="Content-Type" content="text/html; charset=<%= values['charset'] %>" />
185
+ <link rel="stylesheet" href="<%= values['style_url'] %>" type="text/css" media="screen" />
186
+ <script language="JavaScript" type="text/javascript">
187
+ // <![CDATA[
188
+
189
+ function toggleSource( id )
190
+ {
191
+ var elem
192
+ var link
193
+
194
+ if( document.getElementById )
195
+ {
196
+ elem = document.getElementById( id )
197
+ link = document.getElementById( "l_" + id )
198
+ }
199
+ else if ( document.all )
200
+ {
201
+ elem = eval( "document.all." + id )
202
+ link = eval( "document.all.l_" + id )
203
+ }
204
+ else
205
+ return false;
206
+
207
+ if( elem.style.display == "block" )
208
+ {
209
+ elem.style.display = "none"
210
+ link.innerHTML = "show source"
211
+ }
212
+ else
213
+ {
214
+ elem.style.display = "block"
215
+ link.innerHTML = "hide source"
216
+ }
217
+ }
218
+
219
+ function openCode( url )
220
+ {
221
+ window.open( url, "SOURCE_CODE", "width=400,height=400,scrollbars=yes" )
222
+ }
223
+ // ]]>
224
+ </script>
225
+ </head>
226
+ <body>
227
+ <div id="menu">
228
+ <div id="links">
229
+ <a href="http://redhanded.hobix.com/bits/campingAMicroframework.html">backstory</a> |
230
+ <a href="http://code.whytheluckystiff.net/camping/">wiki</a> |
231
+ <a href="http://code.whytheluckystiff.net/camping/newticket">bugs</a> |
232
+ <a href="http://code.whytheluckystiff.net/svn/camping/">svn</a>
233
+ </div>
234
+ <h3 class="title"><%= values['title'] %></h3>
235
+ </div>
236
+ <div id="fullpage">
237
+ <div id="logo"><img src="<%= values['root'] %>/Camping.gif" /></div>
238
+ <div id="pager">
239
+ <strong>Files:</strong>
240
+ <% values['file_list'].each do |file| %>
241
+ <%= href "#{file['href']}", file['name'] %>
242
+ <% end %>
243
+ <% if values['class_list'] %>
244
+ |
245
+ <strong>classes:</strong>
246
+ <% values['class_list'].each do |klass| %>
247
+ <%= href "#{klass['href']}", klass['name'] %>
248
+ <% end %>
249
+ <% end %>
250
+ </ul>
251
+ </div>
252
+
253
+ <%= template_include %>
254
+
255
+ </div>
256
+ </body>
257
+ </html>
258
+ }
259
+
260
+ ###############################################################################
261
+
262
+ FILE_PAGE = <<_FILE_PAGE_
263
+ <div id="<%= values['full_path'] %>" class="page_shade">
264
+ <div class="page">
265
+ <div class="header">
266
+ <div class="path"><%= values['full_path'] %> / <%= values['dtm_modified'] %></div>
267
+ </div>
268
+ #{CONTENTS_XML}
269
+ </div>
270
+ </div>
271
+ _FILE_PAGE_
272
+
273
+ ###################################################################
274
+
275
+ CLASS_PAGE = %{
276
+ <div id="<%= values['full_name'] %>" class="page_shade">
277
+ <div class="page">
278
+ <% if values['parent'] %>
279
+ <h3><%= values['classmod'] %> <%= values['full_name'] %> &lt; <%= href values['par_url'], values['parent'] %></h3>
280
+ <% else %>
281
+ <h3><%= values['classmod'] %> <%= values['full_name'] %></h3>
282
+ <% end %>
283
+
284
+ <% if values['infiles'] %>
285
+ (in files
286
+ <% values['infiles'].each do |file| %>
287
+ <%= href file['full_path_url'], file['full_path'] %>
288
+ <% end %>
289
+ )
290
+ <% end %>
291
+ } + CONTENTS_XML + %{
292
+ </div>
293
+ </div>
294
+ }
295
+
296
+ METHOD_LIST = ""
297
+ ########################## Index ################################
298
+
299
+ FR_INDEX_BODY = %{
300
+ <%= template_include %>
301
+ }
302
+
303
+ FILE_INDEX = %{
304
+ <html>
305
+ <head>
306
+ <meta http-equiv="Content-Type" content="text/html; charset=<%= values['charset'] %>">
307
+ <style>
308
+ <!--
309
+ body {
310
+ background-color: #ddddff;
311
+ font-family: #{FONTS};
312
+ font-size: 11px;
313
+ font-style: normal;
314
+ line-height: 14px;
315
+ color: #000040;
316
+ }
317
+ div.banner {
318
+ background: #0000aa;
319
+ color: white;
320
+ padding: 1;
321
+ margin: 0;
322
+ font-size: 90%;
323
+ font-weight: bold;
324
+ line-height: 1.1;
325
+ text-align: center;
326
+ width: 100%;
327
+ }
328
+
329
+ -->
330
+ </style>
331
+ <base target="docwin">
332
+ </head>
333
+ <body>
334
+ <div class="banner"><%= values['list_title'] %></div>
335
+ <% values['entries'].each do |entry| %>
336
+ <%= href entry['href'], entry['name'] %><br>
337
+ <% end %>
338
+ </body></html>
339
+ }
340
+
341
+ CLASS_INDEX = FILE_INDEX
342
+ METHOD_INDEX = FILE_INDEX
343
+
344
+ INDEX = %{
345
+ <HTML>
346
+ <HEAD>
347
+ <META HTTP-EQUIV="refresh" content="0;URL=<%= values['initial_page'] %>">
348
+ <TITLE><%= values['realtitle'] %></TITLE>
349
+ </HEAD>
350
+ <BODY>
351
+ Click <a href="<%= values['initial_page'] %>">here</a> to open the Camping docs.
352
+ </BODY>
353
+ </HTML>
354
+ }
355
+
356
+ end
357
+ end
@@ -9,23 +9,6 @@
9
9
  # nicely with piles of documentation everywhere. This documentation is entirely
10
10
  # generated from lib/camping-unabridged.rb using RDoc and our "flipbook" template
11
11
  # found in the extras directory of any camping distribution.
12
- #
13
- # == Requirements
14
- #
15
- # Camping requires at least Ruby 1.8.2.
16
- #
17
- # Camping depends on the following libraries. If you install through RubyGems,
18
- # these will be automatically installed for you.
19
- #
20
- # * ActiveRecord, used in your models.
21
- # ActiveRecord is an object-to-relational database mapper with adapters
22
- # for SQLite3, MySQL, PostgreSQL, SQL Server and more.
23
- # * Markaby, used in your views to describe HTML in plain Ruby.
24
- #
25
- # Camping also works well with Mongrel, the swift Ruby web server.
26
- # http://rubyforge.org/projects/mongrel Mongrel comes with examples
27
- # in its <tt>examples/camping</tt> directory.
28
- #
29
12
  %w[uri stringio rack].map { |l| require l }
30
13
 
31
14
  class Object #:nodoc:
@@ -34,7 +17,11 @@ class Object #:nodoc:
34
17
  end
35
18
  end
36
19
 
37
- # == Camping
20
+ # == Camping
21
+ # TODO: Tutorial: Camping.goes, MVC (link to Controllers, Models, Views where
22
+ # they're described in detail), Camping Server (for development), Rack
23
+ # (for production). the create-method. Service overload too, perhaps?
24
+ # Overriding r404, r500 and r501.
38
25
  #
39
26
  # The camping module contains three modules for separating your application:
40
27
  #
@@ -47,6 +34,7 @@ end
47
34
  # * Camping::Helpers which can be used in controllers and views.
48
35
  #
49
36
  # == The Camping Server
37
+ # TODO: Only for development.
50
38
  #
51
39
  # How do you run Camping apps? Oh, uh... The Camping Server!
52
40
  #
@@ -84,6 +72,7 @@ end
84
72
  # end
85
73
  # end
86
74
  #
75
+ # TODO: Wiki is down.
87
76
  # For more tips, see http://code.whytheluckystiff.net/camping/wiki/GiveUsTheCreateMethod.
88
77
  module Camping
89
78
  C = self
@@ -91,6 +80,7 @@ module Camping
91
80
  P = "<h1>Cam\ping Problem!</h1><h2>%s</h2>"
92
81
  U = Rack::Utils
93
82
  Apps = []
83
+ # TODO: @input[:page] != @input['page']
94
84
  # An object-like Hash.
95
85
  # All Camping query string and cookie variables are loaded as this.
96
86
  #
@@ -125,7 +115,8 @@ module Camping
125
115
  end
126
116
  undef id, type
127
117
  end
128
-
118
+
119
+ # TODO: Fair enough. Maybe complete the ActionPack example?
129
120
  # Helpers contains methods available in your controllers and views. You may add
130
121
  # methods of your own to this module, including many helper methods from Rails.
131
122
  # This is analogous to Rails' <tt>ApplicationHelper</tt> module.
@@ -190,7 +181,7 @@ module Camping
190
181
  # is assigned to route <tt>/logout</tt>. The HTML will come out as:
191
182
  #
192
183
  # <div id="menu">
193
- # <a href="//localhost:3301/frodo/">Home</a>
184
+ # <a href="http://localhost:3301/frodo/">Home</a>
194
185
  # <a href="/frodo/profile">Profile</a>
195
186
  # <a href="/frodo/logout">Logout</a>
196
187
  # <a href="http://google.com">Google</a>
@@ -251,6 +242,7 @@ module Camping
251
242
  # Forgivable, considering that it's only really a handful of methods and accessors.
252
243
  #
253
244
  # == Treating controller methods like Response objects
245
+ # TODO: I don't think this belongs here. Either Controllers or Camping.
254
246
  #
255
247
  # Camping originally came with a barebones Response object, but it's often much more readable
256
248
  # to just use your controller as the response.
@@ -279,6 +271,7 @@ module Camping
279
271
  #
280
272
  module Base
281
273
  attr_accessor :input, :cookies, :headers, :body, :status, :root
274
+ M = proc { |_, o, n| o.merge(n, &M) }
282
275
 
283
276
  # Display a view, calling it by its method name +m+. If a <tt>layout</tt>
284
277
  # method is found in Camping::Views, it will be used to wrap the HTML.
@@ -328,6 +321,7 @@ module Camping
328
321
  # You can also switch the body and the header in order to support Rack:
329
322
  #
330
323
  # r(302, {'Location' => self / "/view/12"}, '')
324
+ # r(another_app.call(@env))
331
325
  #
332
326
  # See also: #r404, #r500 and #r501
333
327
  def r(s, b, h = {})
@@ -367,8 +361,8 @@ module Camping
367
361
  # end
368
362
  #
369
363
  # See: I
370
- def r404(p=env.PATH)
371
- r(404, P % "#{p} not found")
364
+ def r404(p)
365
+ P % "#{p} not found"
372
366
  end
373
367
 
374
368
  # If there is a parse error in Camping or in your application's source code, it will not be caught
@@ -378,15 +372,15 @@ module Camping
378
372
  # You can overide it, but if you have an error in here, it will be uncaught !
379
373
  #
380
374
  # See: I
381
- def r500(k,m,x)
382
- r(500, P % "#{k}.#{m}" + "<h3>#{x.class} #{x.message}: <ul>#{x.backtrace.map{|b|"<li>#{b}</li>"}}</ul></h3>")
375
+ def r500(k,m,e)
376
+ raise e
383
377
  end
384
378
 
385
379
  # Called if an undefined method is called on a Controller, along with the request method +m+ (GET, POST, etc.)
386
380
  #
387
381
  # See: I
388
- def r501(m=@method)
389
- r(501, P % "#{m.upcase} not implemented")
382
+ def r501(m)
383
+ P % "#{m.upcase} not implemented"
390
384
  end
391
385
 
392
386
  # Turn a controller into an array. This is designed to be used to pipe
@@ -401,46 +395,41 @@ module Camping
401
395
  # end
402
396
  # end
403
397
  def to_a
404
- @response.body = (@body.respond_to?(:each) ? @body : '')
405
- @response.status = @status
406
- @response.headers.merge!(@headers)
398
+ r = Rack::Response.new(@body, @status, @headers)
407
399
  @cookies.each do |k, v|
408
400
  v = {:value => v, :path => self / "/"} if String===v
409
- @response.set_cookie(k, v) if @request.cookies[k] != v
401
+ r.set_cookie(k, v)
410
402
  end
411
- @response.to_a
403
+ r.to_a
412
404
  end
413
405
 
414
- def initialize(env) #:nodoc:
415
- @request, @response, @env =
416
- Rack::Request.new(env), Rack::Response.new, env
417
- @root, @input, @cookies,
418
- @headers, @status =
419
- @env.SCRIPT_NAME.sub(/\/$/,''),
420
- H[@request.params], H[@request.cookies],
421
- @response.headers, @response.status
422
-
423
- @input.each do |k, v|
424
- if k[-2..-1] == "[]"
425
- @input[k[0..-3]] = @input.delete(k)
426
- elsif k =~ /(.*)\[([^\]]+)\]$/
427
- (@input[$1] ||= H[])[$2] = @input.delete(k)
428
- end
406
+ def initialize(env, m) #:nodoc:
407
+ r = @request = Rack::Request.new(@env = env)
408
+ @root, p, @cookies,
409
+ @headers, @status, @method =
410
+ (env.SCRIPT_NAME||'').sub(/\/$/,''),
411
+ H[r.params], H[r.cookies],
412
+ {}, m =~ /r(\d+)/ ? $1.to_i : 200, m
413
+
414
+ @input = p.inject(H[]) do |h, (k, v)|
415
+ h.merge(k.split(/[\]\[]+/).reverse.inject(v) { |x, i| H[i => x] }, &M)
429
416
  end
430
417
  end
431
418
 
419
+ # TODO: The wiki is down. Service overload should probably go in Camping.
432
420
  # All requests pass through this method before going to the controller. Some magic
433
421
  # in Camping can be performed by overriding this method.
434
422
  #
435
423
  # See http://code.whytheluckystiff.net/camping/wiki/BeforeAndAfterOverrides for more
436
424
  # on before and after overrides with Camping.
437
425
  def service(*a)
438
- r = catch(:halt){send(@env.REQUEST_METHOD.downcase, *a)}
426
+ r = catch(:halt){send(@method, *a)}
439
427
  @body ||= r
440
428
  self
441
429
  end
442
430
  end
443
-
431
+
432
+ # TODO: @input & @cookies at least.
444
433
  # Controllers is a module for placing classes which handle URLs. This is done
445
434
  # by defining a route to each class using the Controllers::R method.
446
435
  #
@@ -510,7 +499,7 @@ module Camping
510
499
  [I, 'r404', p]
511
500
  end
512
501
 
513
- N = H.new { |_,x| x.downcase }.merge! "N" => '(\d+)', "X" => '(\w+)', "Index" => ''
502
+ N = H.new { |_,x| x.downcase }.merge! "N" => '(\d+)', "X" => '([^/]+)', "Index" => ''
514
503
  # The route maker, this is called by Camping internally, you shouldn't need to call it.
515
504
  #
516
505
  # Still, it's worth know what this method does. Since Ruby doesn't keep track of class
@@ -533,8 +522,7 @@ module Camping
533
522
  end
534
523
 
535
524
  # Internal controller with no route. Used by #D and C.call to show internal messages.
536
- class I < R()
537
- end
525
+ I = R()
538
526
  end
539
527
  X = Controllers
540
528
 
@@ -559,10 +547,12 @@ module Camping
559
547
  # And array with [statuc, headers, body] is expected at the output.
560
548
  def call(e)
561
549
  X.M
562
- e = H[e.to_hash]
563
- k,m,*a=X.D e.PATH_INFO,(e.REQUEST_METHOD||'get').downcase
564
- e.REQUEST_METHOD = m
565
- k.new(e).service(*a).to_a
550
+ e = H[e]
551
+ p = e.PATH_INFO = U.unescape(e.PATH_INFO)
552
+ k,m,*a=X.D p,(e.REQUEST_METHOD||'get').downcase
553
+ k.new(e,m).service(*a).to_a
554
+ rescue
555
+ r500(:I, k, m, $!, :env => e).to_a
566
556
  end
567
557
 
568
558
  # The Camping scriptable dispatcher. Any unhandled method call to the app module will
@@ -585,14 +575,15 @@ module Camping
585
575
  #
586
576
  def method_missing(m, c, *a)
587
577
  X.M
588
- h=Hash===a[-1]?H[a.pop]:{}
589
- e=H[h[:env]||{}].merge!({'rack.input'=>StringIO.new,'REQUEST_METHOD'=>m.to_s})
590
- k = X.const_get(c).new(H[e])
591
- k.send("input=",h[:input]) if h[:input]
578
+ h = Hash === a[-1] ? a.pop : {}
579
+ e = H[Rack::MockRequest.env_for('',h[:env]||{})]
580
+ k = X.const_get(c).new(e,m.to_s)
581
+ k.send("input=", h[:input]) if h[:input]
592
582
  k.service(*a)
593
583
  end
594
584
  end
595
-
585
+
586
+ # TODO: More examples.
596
587
  # Views is an empty module for storing methods which create HTML. The HTML is described
597
588
  # using the Markaby language.
598
589
  #
@@ -601,7 +592,8 @@ module Camping
601
592
  # If your Views module has a <tt>layout</tt> method defined, it will be called with a block
602
593
  # which will insert content from your view.
603
594
  module Views; include X, Helpers end
604
-
595
+
596
+ # TODO: Migrations
605
597
  # Models is an empty Ruby module for housing model classes derived
606
598
  # from ActiveRecord::Base. As a shortcut, you may derive from Base
607
599
  # which is an alias for ActiveRecord::Base.