picnic 0.8.0 → 0.8.1

Sign up to get free protection for your applications and to get access to all the features.
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.