zuk-picnic 0.7.999.20090212

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. data/CHANGELOG.txt +1 -0
  2. data/History.txt +68 -0
  3. data/LICENSE.txt +165 -0
  4. data/Manifest.txt +29 -0
  5. data/README.txt +31 -0
  6. data/Rakefile +62 -0
  7. data/lib/picnic/authentication.rb +218 -0
  8. data/lib/picnic/cli.rb +165 -0
  9. data/lib/picnic/conf.rb +135 -0
  10. data/lib/picnic/controllers.rb +4 -0
  11. data/lib/picnic/logger.rb +41 -0
  12. data/lib/picnic/server.rb +98 -0
  13. data/lib/picnic/service_control.rb +274 -0
  14. data/lib/picnic/version.rb +9 -0
  15. data/lib/picnic.rb +48 -0
  16. data/setup.rb +1585 -0
  17. data/test/picnic_test.rb +11 -0
  18. data/test/test_helper.rb +2 -0
  19. data/vendor/camping-2.0.20090212/CHANGELOG +118 -0
  20. data/vendor/camping-2.0.20090212/COPYING +18 -0
  21. data/vendor/camping-2.0.20090212/README +119 -0
  22. data/vendor/camping-2.0.20090212/Rakefile +174 -0
  23. data/vendor/camping-2.0.20090212/bin/camping +99 -0
  24. data/vendor/camping-2.0.20090212/doc/camping.1.gz +0 -0
  25. data/vendor/camping-2.0.20090212/examples/README +5 -0
  26. data/vendor/camping-2.0.20090212/examples/blog.rb +375 -0
  27. data/vendor/camping-2.0.20090212/examples/campsh.rb +629 -0
  28. data/vendor/camping-2.0.20090212/examples/tepee.rb +242 -0
  29. data/vendor/camping-2.0.20090212/extras/Camping.gif +0 -0
  30. data/vendor/camping-2.0.20090212/extras/flipbook_rdoc.rb +491 -0
  31. data/vendor/camping-2.0.20090212/extras/permalink.gif +0 -0
  32. data/vendor/camping-2.0.20090212/lib/camping/ar/session.rb +132 -0
  33. data/vendor/camping-2.0.20090212/lib/camping/ar.rb +78 -0
  34. data/vendor/camping-2.0.20090212/lib/camping/mab.rb +26 -0
  35. data/vendor/camping-2.0.20090212/lib/camping/reloader.rb +163 -0
  36. data/vendor/camping-2.0.20090212/lib/camping/server.rb +158 -0
  37. data/vendor/camping-2.0.20090212/lib/camping/session.rb +74 -0
  38. data/vendor/camping-2.0.20090212/lib/camping-unabridged.rb +638 -0
  39. data/vendor/camping-2.0.20090212/lib/camping.rb +54 -0
  40. data/vendor/camping-2.0.20090212/setup.rb +1551 -0
  41. data/vendor/camping-2.0.20090212/test/apps/env_debug.rb +65 -0
  42. data/vendor/camping-2.0.20090212/test/apps/forms.rb +95 -0
  43. data/vendor/camping-2.0.20090212/test/apps/misc.rb +86 -0
  44. data/vendor/camping-2.0.20090212/test/apps/sessions.rb +38 -0
  45. data/vendor/camping-2.0.20090212/test/test_camping.rb +54 -0
  46. metadata +128 -0
@@ -0,0 +1,491 @@
1
+ CAMPING_EXTRAS_DIR = File.expand_path(File.dirname(__FILE__))
2
+
3
+ module Generators
4
+ class HTMLGenerator
5
+ def generate_html
6
+ @files_and_classes = {
7
+ 'allfiles' => gen_into_index(@files),
8
+ 'allclasses' => gen_into_index(@classes),
9
+ "initial_page" => main_url,
10
+ 'realtitle' => CGI.escapeHTML(@options.title),
11
+ 'charset' => @options.charset
12
+ }
13
+
14
+ # the individual descriptions for files and classes
15
+ gen_into(@files)
16
+ gen_into(@classes)
17
+ gen_main_index
18
+
19
+ # this method is defined in the template file
20
+ write_extra_pages if defined? write_extra_pages
21
+ end
22
+
23
+ def gen_into(list)
24
+ hsh = @files_and_classes.dup
25
+ list.each do |item|
26
+ if item.document_self
27
+ op_file = item.path
28
+ hsh['root'] = item.path.split("/").map { ".." }[1..-1].join("/")
29
+ item.instance_variable_set("@values", hsh)
30
+ File.makedirs(File.dirname(op_file))
31
+ File.open(op_file, "w") { |file| item.write_on(file) }
32
+ end
33
+ end
34
+ end
35
+
36
+ def gen_into_index(list)
37
+ res = []
38
+ list.each do |item|
39
+ hsh = item.value_hash
40
+ hsh['href'] = item.path
41
+ hsh['name'] = item.index_name
42
+ res << hsh
43
+ end
44
+ res
45
+ end
46
+
47
+ def gen_main_index
48
+ template = TemplatePage.new(RDoc::Page::INDEX)
49
+ File.open("index.html", "w") do |f|
50
+ values = @files_and_classes.dup
51
+ if @options.inline_source
52
+ values['inline_source'] = true
53
+ end
54
+ template.write_html_on(f, values)
55
+ end
56
+ ['Camping.gif', 'permalink.gif'].each do |img|
57
+ ipath = File.join(CAMPING_EXTRAS_DIR, img)
58
+ File.copy(ipath, img)
59
+ end
60
+ end
61
+ end
62
+ end
63
+
64
+
65
+ module RDoc
66
+ module Page
67
+ ######################################################################
68
+ #
69
+ # The following is used for the -1 option
70
+ #
71
+
72
+ FONTS = "verdana,arial,'Bitstream Vera Sans',helvetica,sans-serif"
73
+
74
+ STYLE = %{
75
+ body, th, td {
76
+ font: normal 14px verdana,arial,'Bitstream Vera Sans',helvetica,sans-serif;
77
+ line-height: 160%;
78
+ padding: 0; margin: 0;
79
+ margin-bottom: 30px;
80
+ /* background-color: #402; */
81
+ background-color: #694;
82
+ }
83
+ h1, h2, h3, h4 {
84
+ font-family: Utopia, Georgia, serif;
85
+ font-weight: bold;
86
+ letter-spacing: -0.018em;
87
+ }
88
+ h1 { font-size: 24px; margin: .15em 1em 0 0 }
89
+ h2 { font-size: 24px }
90
+ h3 { font-size: 19px }
91
+ h4 { font-size: 17px; font-weight: normal; }
92
+ h4.ruled { border-bottom: solid 1px #CC9; }
93
+ h2.ruled { padding-top: 35px; border-top: solid 1px #AA5; }
94
+
95
+ /* Link styles */
96
+ :link, :visited {
97
+ color: #00b;
98
+ }
99
+ :link:hover, :visited:hover {
100
+ background-color: #eee;
101
+ color: #B22;
102
+ }
103
+ #fullpage {
104
+ width: 720px;
105
+ margin: 0 auto;
106
+ }
107
+ .page_shade, .page {
108
+ padding: 0px 5px 5px 0px;
109
+ background-color: #fcfcf9;
110
+ border: solid 1px #983;
111
+ }
112
+ .page {
113
+ margin-left: -5px;
114
+ margin-top: -5px;
115
+ padding: 20px 35px;
116
+ }
117
+ .page .header {
118
+ float: right;
119
+ color: #777;
120
+ font-size: 10px;
121
+ }
122
+ .page h1, .page h2, .page h3 {
123
+ clear: both;
124
+ text-align: center;
125
+ }
126
+ #pager {
127
+ padding: 10px 4px;
128
+ color: white;
129
+ font-size: 11px;
130
+ }
131
+ #pager :link, #pager :visited {
132
+ color: #bfb;
133
+ padding: 0px 5px;
134
+ }
135
+ #pager :link:hover, #pager :visited:hover {
136
+ background-color: #262;
137
+ color: white;
138
+ }
139
+ #logo { float: left; }
140
+ #menu { background-color: #dfa; padding: 4px 12px; margin: 0; }
141
+ #menu h3 { padding: 0; margin: 0; }
142
+ #menu #links { float: right; }
143
+ pre { font-weight: bold; color: #730; }
144
+ tt { color: #703; font-size: 12pt; }
145
+ .dyn-source { background-color: #775915; padding: 4px 8px; margin: 0; display: none; }
146
+ .dyn-source pre { color: #DDDDDD; font-size: 8pt; }
147
+ .source-link { text-align: right; font-size: 8pt; }
148
+ .ruby-comment { color: green; font-style: italic }
149
+ .ruby-constant { color: #CCDDFF; font-weight: bold; }
150
+ .ruby-identifier { color: #CCCCCC; }
151
+ .ruby-ivar { color: #BBCCFF; }
152
+ .ruby-keyword { color: #EEEEFF; font-weight: bold }
153
+ .ruby-node { color: #FFFFFF; }
154
+ .ruby-operator { color: #CCCCCC; }
155
+ .ruby-regexp { color: #DDFFDD; }
156
+ .ruby-value { color: #FFAAAA; font-style: italic }
157
+ .kw { color: #DDDDFF; font-weight: bold }
158
+ .cmt { color: #CCFFCC; font-style: italic }
159
+ .str { color: #EECCCC; font-style: italic }
160
+ .re { color: #EECCCC; }
161
+ }
162
+
163
+ CONTENTS_XML = %{
164
+ IF:description
165
+ %description%
166
+ ENDIF:description
167
+
168
+ IF:requires
169
+ <h4>Requires:</h4>
170
+ <ul>
171
+ START:requires
172
+ IF:aref
173
+ <li><a href="%aref%">%name%</a></li>
174
+ ENDIF:aref
175
+ IFNOT:aref
176
+ <li>%name%</li>
177
+ ENDIF:aref
178
+ END:requires
179
+ </ul>
180
+ ENDIF:requires
181
+
182
+ IF:attributes
183
+ <h4>Attributes</h4>
184
+ <table>
185
+ START:attributes
186
+ <tr><td>%name%</td><td>%rw%</td><td>%a_desc%</td></tr>
187
+ END:attributes
188
+ </table>
189
+ ENDIF:attributes
190
+
191
+ IF:includes
192
+ <h4>Includes</h4>
193
+ <ul>
194
+ START:includes
195
+ IF:aref
196
+ <li><a href="%aref%">%name%</a></li>
197
+ ENDIF:aref
198
+ IFNOT:aref
199
+ <li>%name%</li>
200
+ ENDIF:aref
201
+ END:includes
202
+ </ul>
203
+ ENDIF:includes
204
+
205
+ START:sections
206
+ IF:method_list
207
+ <h2 class="ruled">Methods</h2>
208
+ START:method_list
209
+ IF:methods
210
+ START:methods
211
+ <h4 class="ruled">%type% %category% method:
212
+ IF:callseq
213
+ <strong><a name="%aref%">%callseq%</a></strong> <a href="#%aref%"><img src="%root%/permalink.gif" border="0" title="Permalink to %callseq%" /></a>
214
+ ENDIF:callseq
215
+ IFNOT:callseq
216
+ <strong><a name="%aref%">%name%%params%</a></strong> <a href="#%aref%"><img src="%root%/permalink.gif" border="0" title="Permalink to %type% %category% method: %name%" /></a></h4>
217
+ ENDIF:callseq
218
+
219
+ IF:m_desc
220
+ %m_desc%
221
+ ENDIF:m_desc
222
+
223
+ IF:sourcecode
224
+ <div class="sourcecode">
225
+ <p class="source-link">[ <a href="javascript:toggleSource('%aref%_source')" id="l_%aref%_source">show source</a> ]</p>
226
+ <div id="%aref%_source" class="dyn-source">
227
+ <pre>
228
+ %sourcecode%
229
+ </pre>
230
+ </div>
231
+ </div>
232
+ ENDIF:sourcecode
233
+ END:methods
234
+ ENDIF:methods
235
+ END:method_list
236
+ ENDIF:method_list
237
+ END:sections
238
+ }
239
+
240
+ ############################################################################
241
+
242
+
243
+ BODY = %{
244
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
245
+ <html>
246
+ <head>
247
+ <title>
248
+ IF:title
249
+ %realtitle% &raquo; %title%
250
+ ENDIF:title
251
+ IFNOT:title
252
+ %realtitle%
253
+ ENDIF:title
254
+ </title>
255
+ <meta http-equiv="Content-Type" content="text/html; charset=%charset%" />
256
+ <link rel="stylesheet" href="%style_url%" type="text/css" media="screen" />
257
+ <script language="JavaScript" type="text/javascript">
258
+ // <![CDATA[
259
+
260
+ function toggleSource( id )
261
+ {
262
+ var elem
263
+ var link
264
+
265
+ if( document.getElementById )
266
+ {
267
+ elem = document.getElementById( id )
268
+ link = document.getElementById( "l_" + id )
269
+ }
270
+ else if ( document.all )
271
+ {
272
+ elem = eval( "document.all." + id )
273
+ link = eval( "document.all.l_" + id )
274
+ }
275
+ else
276
+ return false;
277
+
278
+ if( elem.style.display == "block" )
279
+ {
280
+ elem.style.display = "none"
281
+ link.innerHTML = "show source"
282
+ }
283
+ else
284
+ {
285
+ elem.style.display = "block"
286
+ link.innerHTML = "hide source"
287
+ }
288
+ }
289
+
290
+ function openCode( url )
291
+ {
292
+ window.open( url, "SOURCE_CODE", "width=400,height=400,scrollbars=yes" )
293
+ }
294
+ // ]]>
295
+ </script>
296
+ </head>
297
+ <body>
298
+ <div id="menu">
299
+ <div id="links">
300
+ <a href="http://redhanded.hobix.com/bits/campingAMicroframework.html">backstory</a> |
301
+ <a href="http://code.whytheluckystiff.net/camping/">wiki</a> |
302
+ <a href="http://code.whytheluckystiff.net/camping/newticket">bugs</a> |
303
+ <a href="http://code.whytheluckystiff.net/svn/camping/">svn</a>
304
+ </div>
305
+ <h3 class="title">%title%</h3>
306
+ </div>
307
+ <div id="fullpage">
308
+ <div id="logo"><img src="%root%/Camping.gif" /></div>
309
+ <div id="pager">
310
+ <strong>Files:</strong>
311
+ START:allfiles
312
+ <a href="%root%/%href%" value="%title%">%name%</a>
313
+ END:allfiles
314
+ IF:allclasses
315
+ |
316
+ <strong>classes:</strong>
317
+ START:allclasses
318
+ <a href="%root%/%href%" title="%title%">%name%</a>
319
+ END:allclasses
320
+ ENDIF:allclasses
321
+ </ul>
322
+ </div>
323
+
324
+ !INCLUDE!
325
+
326
+ </div>
327
+ </body>
328
+ </html>
329
+ }
330
+
331
+ ###############################################################################
332
+
333
+ FILE_PAGE = <<_FILE_PAGE_
334
+ <div id="%full_path%" class="page_shade">
335
+ <div class="page">
336
+ <div class="header">
337
+ <div class="path">%full_path% / %dtm_modified%</div>
338
+ </div>
339
+ #{CONTENTS_XML}
340
+ </div>
341
+ </div>
342
+ _FILE_PAGE_
343
+
344
+ ###################################################################
345
+
346
+ CLASS_PAGE = %{
347
+ <div id="%full_name%" class="page_shade">
348
+ <div class="page">
349
+ IF:parent
350
+ <h3>%classmod% %full_name% &lt; HREF:par_url:parent:</h3>
351
+ ENDIF:parent
352
+ IFNOT:parent
353
+ <h3>%classmod% %full_name%</h3>
354
+ ENDIF:parent
355
+
356
+ IF:infiles
357
+ (in files
358
+ START:infiles
359
+ HREF:full_path_url:full_path:
360
+ END:infiles
361
+ )
362
+ ENDIF:infiles
363
+ } + CONTENTS_XML + %{
364
+ </div>
365
+ </div>
366
+ }
367
+
368
+ ###################################################################
369
+
370
+ METHOD_LIST = %{
371
+ IF:includes
372
+ <div class="tablesubsubtitle">Included modules</div><br>
373
+ <div class="name-list">
374
+ START:includes
375
+ <span class="method-name">HREF:aref:name:</span>
376
+ END:includes
377
+ </div>
378
+ ENDIF:includes
379
+
380
+ IF:method_list
381
+ START:method_list
382
+ IF:methods
383
+ <table cellpadding=5 width="100%">
384
+ <tr><td class="tablesubtitle">%type% %category% methods</td></tr>
385
+ </table>
386
+ START:methods
387
+ <table width="100%" cellspacing = 0 cellpadding=5 border=0>
388
+ <tr><td class="methodtitle">
389
+ <a name="%aref%">
390
+ IF:callseq
391
+ <b>%callseq%</b>
392
+ ENDIF:callseq
393
+ IFNOT:callseq
394
+ <b>%name%</b>%params%
395
+ ENDIF:callseq
396
+ IF:codeurl
397
+ <a href="%codeurl%" target="source" class="srclink">src</a>
398
+ ENDIF:codeurl
399
+ </a></td></tr>
400
+ </table>
401
+ IF:m_desc
402
+ <div class="description">
403
+ %m_desc%
404
+ </div>
405
+ ENDIF:m_desc
406
+ IF:aka
407
+ <div class="aka">
408
+ This method is also aliased as
409
+ START:aka
410
+ <a href="%aref%">%name%</a>
411
+ END:aka
412
+ </div>
413
+ ENDIF:aka
414
+ IF:sourcecode
415
+ <div class="sourcecode">
416
+ <p class="source-link">[ <a href="javascript:toggleSource('%aref%_source')" id="l_%aref%_source">show source</a> ]</p>
417
+ <div id="%aref%_source" class="dyn-source">
418
+ <pre>
419
+ %sourcecode%
420
+ </pre>
421
+ </div>
422
+ </div>
423
+ ENDIF:sourcecode
424
+ END:methods
425
+ ENDIF:methods
426
+ END:method_list
427
+ ENDIF:method_list
428
+ }
429
+
430
+
431
+ ########################## Index ################################
432
+
433
+ FR_INDEX_BODY = %{
434
+ !INCLUDE!
435
+ }
436
+
437
+ FILE_INDEX = %{
438
+ <html>
439
+ <head>
440
+ <meta http-equiv="Content-Type" content="text/html; charset=%charset%">
441
+ <style>
442
+ <!--
443
+ body {
444
+ background-color: #ddddff;
445
+ font-family: #{FONTS};
446
+ font-size: 11px;
447
+ font-style: normal;
448
+ line-height: 14px;
449
+ color: #000040;
450
+ }
451
+ div.banner {
452
+ background: #0000aa;
453
+ color: white;
454
+ padding: 1;
455
+ margin: 0;
456
+ font-size: 90%;
457
+ font-weight: bold;
458
+ line-height: 1.1;
459
+ text-align: center;
460
+ width: 100%;
461
+ }
462
+
463
+ -->
464
+ </style>
465
+ <base target="docwin">
466
+ </head>
467
+ <body>
468
+ <div class="banner">%list_title%</div>
469
+ START:entries
470
+ <a href="%href%">%name%</a><br>
471
+ END:entries
472
+ </body></html>
473
+ }
474
+
475
+ CLASS_INDEX = FILE_INDEX
476
+ METHOD_INDEX = FILE_INDEX
477
+
478
+ INDEX = %{
479
+ <HTML>
480
+ <HEAD>
481
+ <META HTTP-EQUIV="refresh" content="0;URL=%initial_page%">
482
+ <TITLE>%realtitle%</TITLE>
483
+ </HEAD>
484
+ <BODY>
485
+ Click <a href="%initial_page%">here</a> to open the Camping docs.
486
+ </BODY>
487
+ </HTML>
488
+ }
489
+
490
+ end
491
+ end
@@ -0,0 +1,132 @@
1
+ # == About camping/ar/session.rb
2
+ #
3
+ # This file contains two modules which supply basic sessioning to your Camping app.
4
+ # Again, we're dealing with a pretty little bit of code: approx. 60 lines.
5
+ #
6
+ # * Camping::Models::Session is a module which adds a single <tt>sessions</tt> table
7
+ # to your database.
8
+ # * Camping::ARSession is a module which you will mix into your application (or into
9
+ # specific controllers which require sessions) to supply a <tt>@state</tt> variable
10
+ # you can use in controllers and views.
11
+ #
12
+ # For a basic tutorial, see the *Getting Started* section of the Camping::ARSession module.
13
+ require 'camping'
14
+ require 'camping/ar'
15
+
16
+ module Camping::Models
17
+ # A database table for storing Camping sessions. Contains a unique 32-character hashid, a
18
+ # creation timestamp, and a column of serialized data called <tt>ivars</tt>.
19
+ class Session < Base
20
+ serialize :ivars
21
+ set_primary_key :hashid
22
+
23
+ def []=(k, v) # :nodoc:
24
+ self.ivars[k] = v
25
+ end
26
+ def [](k) # :nodoc:
27
+ self.ivars[k] rescue nil
28
+ end
29
+
30
+ protected
31
+ RAND_CHARS = [*'A'..'Z'] + [*'0'..'9'] + [*'a'..'z']
32
+ def before_create
33
+ rand_max = RAND_CHARS.size
34
+ sid = (0...32).inject("") { |ret,_| ret << RAND_CHARS[rand(rand_max)] }
35
+ write_attribute('hashid', sid)
36
+ end
37
+
38
+ # Generates a new session ID and creates a row for the new session in the database.
39
+ def self.generate cookies
40
+ sess = Session.create :ivars => Camping::H[]
41
+ cookies.camping_sid = sess.hashid
42
+ sess
43
+ end
44
+
45
+ # Gets the existing session based on the <tt>camping_sid</tt> available in cookies.
46
+ # If none is found, generates a new session.
47
+ def self.persist cookies
48
+ session = nil
49
+ if cookies.camping_sid
50
+ session = Camping::Models::Session.find_by_hashid cookies.camping_sid
51
+ end
52
+ unless session
53
+ session = Camping::Models::Session.generate cookies
54
+ end
55
+ session
56
+ end
57
+
58
+ # Builds the session table in the database. To be used in your application's
59
+ # <tt>create</tt> method.
60
+ #
61
+ # Like so:
62
+ #
63
+ # def Blog.create
64
+ # Camping::Models::Session.create_schema
65
+ # unless Blog::Models::Post.table_exists?
66
+ # ActiveRecord::Schema.define(&Blog::Models.schema)
67
+ # end
68
+ # end
69
+ #
70
+ def self.create_schema
71
+ unless table_exists?
72
+ ActiveRecord::Schema.define do
73
+ create_table :sessions, :force => true, :id => false do |t|
74
+ t.column :hashid, :string, :limit => 32, :null => false
75
+ t.column :created_at, :datetime
76
+ t.column :ivars, :text
77
+ end
78
+ add_index :sessions, [:hashid], :unique => true
79
+ end
80
+ reset_column_information
81
+ end
82
+ end
83
+ end
84
+ Session.partial_updates = false if Session.respond_to?(:partial_updates=)
85
+ end
86
+
87
+ module Camping
88
+ # The Camping::ARSession module is designed to be mixed into your application or into specific
89
+ # controllers which require sessions. This module defines a <tt>service</tt> method which
90
+ # intercepts all requests handed to those controllers.
91
+ #
92
+ # == Getting Started
93
+ #
94
+ # To get sessions working for your application:
95
+ #
96
+ # 1. <tt>require 'camping/session'</tt>
97
+ # 2. Mixin the module: <tt>module YourApp; include Camping::ARSession end</tt>
98
+ # 3. In your application's <tt>create</tt> method, add a call to <tt>Camping::Models::Session.create_schema</tt>
99
+ # 4. Throughout your application, use the <tt>@state</tt> var like a hash to store your application's data.
100
+ #
101
+ # If you are unfamiliar with the <tt>create</tt> method, see
102
+ # http://code.whytheluckystiff.net/camping/wiki/GiveUsTheCreateMethod.
103
+ #
104
+ # == A Few Notes
105
+ #
106
+ # * The session ID is stored in a cookie. Look in <tt>@cookies.camping_sid</tt>.
107
+ # * The session data is stored in the <tt>sessions</tt> table in your database.
108
+ # * All mounted Camping apps using this class will use the same database table.
109
+ # * However, your application's data is stored in its own hash.
110
+ # * Session data is only saved if it has changed.
111
+ module ARSession
112
+ # This <tt>service</tt> method, when mixed into controllers, intercepts requests
113
+ # and wraps them with code to start and close the session. If a session isn't found
114
+ # in the database it is created. The <tt>@state</tt> variable is set and if it changes,
115
+ # it is saved back into the database.
116
+ def service(*a)
117
+ session = Camping::Models::Session.persist @cookies
118
+ app = self.class.name.gsub(/^(\w+)::.+$/, '\1')
119
+ @state = (session[app] ||= Camping::H[])
120
+ hash_before = Marshal.dump(@state).hash
121
+ return super(*a)
122
+ ensure
123
+ if session
124
+ hash_after = Marshal.dump(@state).hash
125
+ unless hash_before == hash_after
126
+ session[app] = @state
127
+ session.save
128
+ end
129
+ end
130
+ end
131
+ end
132
+ end
@@ -0,0 +1,78 @@
1
+ class MissingLibrary < Exception #:nodoc: all
2
+ end
3
+ begin
4
+ require 'active_record'
5
+ rescue LoadError => e
6
+ raise MissingLibrary, "ActiveRecord could not be loaded (is it installed?): #{e.message}"
7
+ end
8
+
9
+ $AR_EXTRAS = %{
10
+ Base = ActiveRecord::Base unless const_defined? :Base
11
+
12
+ def Y; ActiveRecord::Base.verify_active_connections!; self; end
13
+
14
+ class SchemaInfo < Base
15
+ end
16
+
17
+ def self.V(n)
18
+ @final = [n, @final.to_i].max
19
+ m = (@migrations ||= [])
20
+ Class.new(ActiveRecord::Migration) do
21
+ meta_def(:version) { n }
22
+ meta_def(:inherited) { |k| m << k }
23
+ end
24
+ end
25
+
26
+ def self.create_schema(opts = {})
27
+ opts[:assume] ||= 0
28
+ opts[:version] ||= @final
29
+ if @migrations
30
+ unless SchemaInfo.table_exists?
31
+ ActiveRecord::Schema.define do
32
+ create_table SchemaInfo.table_name do |t|
33
+ t.column :version, :float
34
+ end
35
+ end
36
+ end
37
+
38
+ si = SchemaInfo.find(:first) || SchemaInfo.new(:version => opts[:assume])
39
+ if si.version < opts[:version]
40
+ @migrations.each do |k|
41
+ k.migrate(:up) if si.version < k.version and k.version <= opts[:version]
42
+ k.migrate(:down) if si.version > k.version and k.version > opts[:version]
43
+ end
44
+ si.update_attributes(:version => opts[:version])
45
+ end
46
+ end
47
+ end
48
+ }
49
+
50
+ module Camping
51
+ module Models
52
+ A = ActiveRecord
53
+ # Base is an alias for ActiveRecord::Base. The big warning I'm going to give you
54
+ # about this: *Base overloads table_name_prefix.* This means that if you have a
55
+ # model class Blog::Models::Post, it's table name will be <tt>blog_posts</tt>.
56
+ #
57
+ # ActiveRecord is not loaded if you never reference this class. The minute you
58
+ # use the ActiveRecord or Camping::Models::Base class, then the ActiveRecord library
59
+ # is loaded.
60
+ Base = A::Base
61
+
62
+ # The default prefix for Camping model classes is the topmost module name lowercase
63
+ # and followed with an underscore.
64
+ #
65
+ # Tepee::Models::Page.table_name_prefix
66
+ # #=> "tepee_pages"
67
+ #
68
+ def Base.table_name_prefix
69
+ "#{name[/\w+/]}_".downcase.sub(/^(#{A}|camping)_/i,'')
70
+ end
71
+ module_eval $AR_EXTRAS
72
+ end
73
+ end
74
+ Camping::S.sub! /autoload\s*:Base\s*,\s*['"]camping\/ar['"]/, ""
75
+ Camping::S.sub! /def\s*Y[;\s]*self[;\s]*end/, $AR_EXTRAS
76
+ Camping::Apps.each do |c|
77
+ c::Models.module_eval $AR_EXTRAS
78
+ end