nitro 0.25.0 → 0.26.0
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.
- data/CHANGELOG +531 -1
- data/ProjectInfo +29 -5
- data/README +1 -1
- data/doc/AUTHORS +12 -6
- data/doc/RELEASES +114 -0
- data/lib/glue/sweeper.rb +71 -0
- data/lib/nitro.rb +19 -12
- data/lib/nitro/adapter/cgi.rb +4 -0
- data/lib/nitro/adapter/webrick.rb +4 -2
- data/lib/nitro/caching.rb +1 -0
- data/lib/nitro/caching/fragments.rb +7 -1
- data/lib/nitro/caching/output.rb +6 -1
- data/lib/nitro/caching/stores.rb +13 -1
- data/lib/nitro/cgi.rb +9 -1
- data/lib/nitro/cgi/request.rb +11 -3
- data/lib/nitro/cgi/utils.rb +24 -2
- data/lib/nitro/compiler.rb +89 -63
- data/lib/nitro/compiler/cleanup.rb +16 -0
- data/lib/nitro/compiler/elements.rb +117 -0
- data/lib/nitro/compiler/markup.rb +3 -1
- data/lib/nitro/compiler/morphing.rb +203 -73
- data/lib/nitro/compiler/script_generator.rb +14 -0
- data/lib/nitro/compiler/shaders.rb +1 -1
- data/lib/nitro/context.rb +5 -6
- data/lib/nitro/controller.rb +43 -21
- data/lib/nitro/dispatcher.rb +86 -37
- data/lib/nitro/element.rb +3 -105
- data/lib/nitro/helper/benchmark.rb +3 -0
- data/lib/nitro/helper/dojo.rb +0 -0
- data/lib/nitro/helper/form.rb +85 -255
- data/lib/nitro/helper/form/controls.rb +274 -0
- data/lib/nitro/helper/javascript.rb +86 -6
- data/lib/nitro/helper/pager.rb +5 -0
- data/lib/nitro/helper/prototype.rb +49 -0
- data/lib/nitro/helper/scriptaculous.rb +0 -0
- data/lib/nitro/helper/xhtml.rb +11 -8
- data/lib/nitro/helper/xml.rb +1 -1
- data/lib/nitro/routing.rb +8 -1
- data/lib/nitro/scaffolding.rb +344 -0
- data/lib/nitro/server.rb +5 -1
- data/lib/nitro/server/runner.rb +19 -15
- data/lib/nitro/session.rb +32 -56
- data/lib/nitro/session/drbserver.rb +1 -1
- data/lib/nitro/session/file.rb +34 -15
- data/lib/nitro/session/memory.rb +13 -4
- data/lib/nitro/session/og.rb +56 -0
- data/proto/public/js/controls.js +30 -1
- data/proto/public/js/dragdrop.js +211 -146
- data/proto/public/js/effects.js +261 -399
- data/proto/public/js/prototype.js +131 -72
- data/proto/public/scaffold/edit.xhtml +10 -3
- data/proto/public/scaffold/form.xhtml +1 -7
- data/proto/public/scaffold/index.xhtml +20 -0
- data/proto/public/scaffold/list.xhtml +15 -8
- data/proto/public/scaffold/new.xhtml +10 -3
- data/proto/public/scaffold/search.xhtml +28 -0
- data/proto/public/scaffold/view.xhtml +8 -0
- data/proto/run.rb +93 -1
- data/src/part/admin.rb +4 -2
- data/src/part/admin/controller.rb +62 -28
- data/src/part/admin/skin.rb +8 -8
- data/src/part/admin/system.css +135 -0
- data/src/part/admin/template/index.xhtml +8 -12
- data/test/nitro/caching/tc_stores.rb +17 -0
- data/test/nitro/tc_caching.rb +1 -4
- data/test/nitro/tc_dispatcher.rb +22 -10
- data/test/nitro/tc_element.rb +1 -1
- data/test/nitro/tc_session.rb +23 -11
- data/test/public/blog/another/very_litle/index.xhtml +1 -0
- metadata +29 -15
- data/lib/nitro/dispatcher/general.rb +0 -62
- data/lib/nitro/dispatcher/nice.rb +0 -57
- data/lib/nitro/scaffold.rb +0 -171
- data/proto/public/index.xhtml +0 -83
- data/proto/public/js/scaffold.js +0 -74
- data/proto/public/settings.xhtml +0 -66
data/ProjectInfo
CHANGED
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
TITLE : &title Nitro
|
|
4
4
|
NAME : &pkg nitro
|
|
5
|
-
VERSION : '0.
|
|
5
|
+
VERSION : '0.26.0'
|
|
6
6
|
STATUS : beta
|
|
7
7
|
|
|
8
8
|
AUTHOR : George Moschovitis
|
|
9
9
|
EMAIL : &email gm@navel.gr
|
|
10
10
|
HOMEPAGE : "http://www.nitrohq.com"
|
|
11
11
|
|
|
12
|
-
SUMMARY:
|
|
12
|
+
SUMMARY: Everything you need to create Web 2.0 applications with Ruby and Javascript
|
|
13
13
|
|
|
14
14
|
DESCRIPTION: >
|
|
15
15
|
Nitro provides everything you need to develop professional Web
|
|
@@ -22,19 +22,43 @@ DESCRIPTION: >
|
|
|
22
22
|
staying standards compliant.
|
|
23
23
|
|
|
24
24
|
DEPENDENCIES:
|
|
25
|
-
- [ og, '= 0.
|
|
26
|
-
- [ gen, '= 0.
|
|
27
|
-
- [ glue, '= 0.
|
|
25
|
+
- [ og, '= 0.26.0' ]
|
|
26
|
+
- [ gen, '= 0.26.0' ]
|
|
27
|
+
- [ glue, '= 0.26.0' ]
|
|
28
28
|
- [ RedCloth, '= 3.0.3' ]
|
|
29
29
|
- [ ruby-breakpoint, '= 0.5' ]
|
|
30
30
|
- [ daemons, '= 0.4.2' ]
|
|
31
31
|
|
|
32
|
+
PACKAGE:
|
|
33
|
+
exclude:
|
|
34
|
+
- dev
|
|
35
|
+
|
|
36
|
+
EXECUTABLES:
|
|
37
|
+
- nitro
|
|
38
|
+
- nitrogen
|
|
39
|
+
|
|
32
40
|
DISTRIBUTE: [ gem, tgz, zip ]
|
|
33
41
|
|
|
34
42
|
RUBYFORGE:
|
|
35
43
|
PROJECT: 'nitro'
|
|
36
44
|
USERNAME: 'gmosx'
|
|
37
45
|
|
|
46
|
+
RDOC:
|
|
47
|
+
- dir: web/rdoc
|
|
48
|
+
template: jamis
|
|
49
|
+
options: ['--all', '--inline-source']
|
|
50
|
+
include:
|
|
51
|
+
- 'lib/nitro/**/*'
|
|
52
|
+
- '[A-Z]*'
|
|
53
|
+
|
|
54
|
+
PUBLISH:
|
|
55
|
+
-
|
|
56
|
+
host: rubyforge
|
|
57
|
+
type: web
|
|
58
|
+
username: gmosx
|
|
59
|
+
project: nitro
|
|
60
|
+
dir: 'web'
|
|
61
|
+
|
|
38
62
|
# Anything to require upfront?
|
|
39
63
|
#TEST:
|
|
40
64
|
# fixture: ''
|
data/README
CHANGED
data/doc/AUTHORS
CHANGED
|
@@ -10,6 +10,9 @@ IDEAS, ADDITIONAL CODING, SUPPORT:
|
|
|
10
10
|
* Guillaume Pierronnet <guillaume.pierronnet@laposte.net>
|
|
11
11
|
Patches, bug reports.
|
|
12
12
|
|
|
13
|
+
* Chris Farmiloe <chris.farmiloe@farmiloe.com>
|
|
14
|
+
Bug fixes, Scaffolding improvements, patches.
|
|
15
|
+
|
|
13
16
|
* James Britt <james_b@neurogami.com>
|
|
14
17
|
Additional code, documentation, design, bug reports.
|
|
15
18
|
|
|
@@ -19,24 +22,27 @@ IDEAS, ADDITIONAL CODING, SUPPORT:
|
|
|
19
22
|
* Aleksi Niemela <Aleksi.Niemela@cs.helsinki.fi>
|
|
20
23
|
Bug fixes, patches, documentation.
|
|
21
24
|
|
|
22
|
-
* Chris Farmiloe <chris.farmiloe@farmiloe.com>
|
|
23
|
-
Bug fixes, Scaffolding improvements, patches.
|
|
24
|
-
|
|
25
25
|
* Rob Pitt <rob@motionpath.co.uk>
|
|
26
26
|
Bug fixes, Scaffolding improvements, patches.
|
|
27
27
|
|
|
28
|
+
* Bryan Soto <bryan.a.soto@gmail.com>
|
|
29
|
+
Small bug fixes, patches.
|
|
30
|
+
|
|
31
|
+
* Brian Bugh <brian@xsi-design.com>
|
|
32
|
+
Fixes, Patches.
|
|
33
|
+
|
|
28
34
|
* Zed A. Shaw <zedshaw@zedshaw.com>
|
|
29
35
|
SCGI adapter.
|
|
30
36
|
|
|
37
|
+
* Peter Abrahamsen <rainhead@gmail.com>
|
|
38
|
+
Documentation, small patches.
|
|
39
|
+
|
|
31
40
|
* Anastasios Koutoumanos <ak@navel.gr>
|
|
32
41
|
Design, bug reports.
|
|
33
42
|
|
|
34
43
|
* TRANS <transfire@gmail.com>
|
|
35
44
|
Small bug fixes, patches.
|
|
36
45
|
|
|
37
|
-
* Bryan Soto <bryan.a.soto@gmail.com>
|
|
38
|
-
Small bug fixes, patches.
|
|
39
|
-
|
|
40
46
|
* Kostas Nasis <kostas@nasis.com>
|
|
41
47
|
Ideas and bug reports.
|
|
42
48
|
|
data/doc/RELEASES
CHANGED
|
@@ -1,3 +1,117 @@
|
|
|
1
|
+
== Version 0.26.0
|
|
2
|
+
|
|
3
|
+
Another step closer to web programming nirvana. This release
|
|
4
|
+
features completely recoded scaffolding, an auto admin system,
|
|
5
|
+
a recoded template-morphing system, a new intelligent dispatcher
|
|
6
|
+
that handles both nice urls and general structure, and so much
|
|
7
|
+
more. Moreover, this is the release with the most community
|
|
8
|
+
contributions. Download now!
|
|
9
|
+
|
|
10
|
+
Most notable changes:
|
|
11
|
+
|
|
12
|
+
* New, intelligent dispatcher handles nice urls automatically,
|
|
13
|
+
without explicit rewrite rules. At the same time, it handles
|
|
14
|
+
sub directories, so you are free to design your app's
|
|
15
|
+
structure as you like.
|
|
16
|
+
|
|
17
|
+
* New template morphing implementation. The morphing compiler
|
|
18
|
+
is fully customizable. You can implement your own morphers and
|
|
19
|
+
add them to the morphing system, here for example is the
|
|
20
|
+
new selected_if morpher:
|
|
21
|
+
|
|
22
|
+
<option value="1" selected_if="@cond">opt1</option>
|
|
23
|
+
|
|
24
|
+
becomes
|
|
25
|
+
<?r if @cond ?>
|
|
26
|
+
<option value="1" selected="selected">opt1</option>
|
|
27
|
+
<?r else ?>
|
|
28
|
+
<option value="1">opt1</option>
|
|
29
|
+
<?r end ?>
|
|
30
|
+
|
|
31
|
+
* New Sweeper mixin. Using this mixin allows you to keep
|
|
32
|
+
the cleanup logic in one place. This logic is called
|
|
33
|
+
automagically by many default Nitro/Og methods (for example
|
|
34
|
+
Og insert/update, scaffolding, etc). You can fully customize
|
|
35
|
+
the behaviour.
|
|
36
|
+
|
|
37
|
+
class Article
|
|
38
|
+
include Sweeper
|
|
39
|
+
|
|
40
|
+
def sweep_affected(action = :all)
|
|
41
|
+
expire_affected_output('articles/view')
|
|
42
|
+
...
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
a = Article[1]
|
|
47
|
+
a.title = 'New'
|
|
48
|
+
a.save # => calls expire_affected.
|
|
49
|
+
|
|
50
|
+
This mixin is typically used to automatically clean up output
|
|
51
|
+
caching files from the filesystem, but you can use it to remove
|
|
52
|
+
temp rows from the database, or temp objects from a drb server
|
|
53
|
+
or anything you like.
|
|
54
|
+
|
|
55
|
+
* Searchable mixin. Include this mixin to your classes to make
|
|
56
|
+
them searchable by the auto administration system.
|
|
57
|
+
|
|
58
|
+
* Added two new session managers (OgSession, FileSession),
|
|
59
|
+
cleaned up the session code.
|
|
60
|
+
|
|
61
|
+
* Better validations implementation. Cleaner code, less evals,
|
|
62
|
+
more flexible and easier to extend.
|
|
63
|
+
|
|
64
|
+
* New scaffolding / auto administration system. The implementation
|
|
65
|
+
is much cleaner and easier to customize. It leverages the latest
|
|
66
|
+
advancements (dispatcher, sweeper, etc) and adds search support,
|
|
67
|
+
pager, breadcrumps and more. You can define your own controls
|
|
68
|
+
to handle properties and relations. Stay tuned for more stuff
|
|
69
|
+
in the near future.
|
|
70
|
+
|
|
71
|
+
* New Og revisable mixin. Just include this mixin in your classes
|
|
72
|
+
and get db backed revision support for free. Here comes an
|
|
73
|
+
example:
|
|
74
|
+
|
|
75
|
+
class Article
|
|
76
|
+
is Revisable
|
|
77
|
+
property :body, String, :revisable => true
|
|
78
|
+
property :title, String
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
Automatically generates the Revision class (and the
|
|
82
|
+
backend schema):
|
|
83
|
+
|
|
84
|
+
class Article::Revision
|
|
85
|
+
|
|
86
|
+
article.revisions
|
|
87
|
+
|
|
88
|
+
article.revise do |a|
|
|
89
|
+
a.title = 'hello'
|
|
90
|
+
a.body = 'world'
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
article.rollback(4)
|
|
94
|
+
|
|
95
|
+
* Bug fixed KirbyBase Og adapter. This works great with the
|
|
96
|
+
new 2.5 gem.
|
|
97
|
+
|
|
98
|
+
* Added more rational defaults, and many predefined options to
|
|
99
|
+
minimize the amount of setup needed to get your app running. Of
|
|
100
|
+
course you can still customize just about everything in Nitro.
|
|
101
|
+
|
|
102
|
+
* Improvements to PostgreSQL automatic generation of foreign key
|
|
103
|
+
constraints.
|
|
104
|
+
|
|
105
|
+
* Added evolution support to the MySql store.
|
|
106
|
+
|
|
107
|
+
* Upgrated to Prototype 1.4 and Scriptaculous 1.5
|
|
108
|
+
|
|
109
|
+
* Updated the examples, check out the improved blog and why_wiki
|
|
110
|
+
examples.
|
|
111
|
+
|
|
112
|
+
* Many, many, many bug fixes and smaller improvements.
|
|
113
|
+
|
|
114
|
+
|
|
1
115
|
== Version 0.25.0
|
|
2
116
|
|
|
3
117
|
This is the first in a series of releases focused on stability
|
data/lib/glue/sweeper.rb
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
require 'glue/aspects'
|
|
2
|
+
|
|
3
|
+
module Glue
|
|
4
|
+
|
|
5
|
+
# This module adds cleanup functionality to managed
|
|
6
|
+
# classes. Override and implement sweep_affected.
|
|
7
|
+
# Typically used to cleanup output caching files from
|
|
8
|
+
# the filesystem. But you can also use it to clean up
|
|
9
|
+
# temp objects in the database or other temp files.
|
|
10
|
+
#--
|
|
11
|
+
# FIXME: find a better name.
|
|
12
|
+
#++
|
|
13
|
+
|
|
14
|
+
module Sweeper
|
|
15
|
+
include Aspects
|
|
16
|
+
|
|
17
|
+
before "sweep_affected(:insert)", :on => :og_insert
|
|
18
|
+
before "sweep_affected(:update)", :on => :og_update
|
|
19
|
+
before "sweep_affected(:delete)", :on => :og_delete
|
|
20
|
+
|
|
21
|
+
#--
|
|
22
|
+
# FIXME: replace with 'extend Nitro::Caching::Output' ?
|
|
23
|
+
# If you change this method, don't forget the Caching::Output
|
|
24
|
+
# expire method.
|
|
25
|
+
#++
|
|
26
|
+
|
|
27
|
+
def self.expire(name)
|
|
28
|
+
begin
|
|
29
|
+
Logger.debug "Sweeper expired cache file '#{Server.public_root}/#{name}'" if $DBG
|
|
30
|
+
FileUtils.rm_rf("#{Server.public_root}/#{name}")
|
|
31
|
+
rescue Object
|
|
32
|
+
# gmosx: is this the right thing to do?
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
private
|
|
37
|
+
|
|
38
|
+
# If needed pass the calling action symbol to allow
|
|
39
|
+
# for conditional expiration.
|
|
40
|
+
# Action takes values from { :insert, :delete, :update }
|
|
41
|
+
# or your own custom enumeration.
|
|
42
|
+
#
|
|
43
|
+
# Generally add lines like the following:
|
|
44
|
+
#
|
|
45
|
+
# expire_affected_output('file_to_expire')
|
|
46
|
+
|
|
47
|
+
def sweep_affected(action = :all)
|
|
48
|
+
end
|
|
49
|
+
alias_method :expire_affected, :sweep_affected
|
|
50
|
+
|
|
51
|
+
#--
|
|
52
|
+
# Generally you don't override this.
|
|
53
|
+
#++
|
|
54
|
+
|
|
55
|
+
def expire_affected_output(name)
|
|
56
|
+
Sweeper.expire(name)
|
|
57
|
+
end
|
|
58
|
+
alias_method :expire_output, :expire_affected_output
|
|
59
|
+
|
|
60
|
+
# Expire affected cached fragments.
|
|
61
|
+
|
|
62
|
+
def expire_affected_fragment(name, options = {})
|
|
63
|
+
Nitro::Caching::Fragments.store.delete(name, options)
|
|
64
|
+
end
|
|
65
|
+
alias_method :expire_fragment, :expire_affected_fragment
|
|
66
|
+
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# * George Moschovitis <gm@navel.gr>
|
data/lib/nitro.rb
CHANGED
|
@@ -16,7 +16,7 @@ module Nitro
|
|
|
16
16
|
|
|
17
17
|
# The version.
|
|
18
18
|
|
|
19
|
-
Version = '0.
|
|
19
|
+
Version = '0.26.0'
|
|
20
20
|
|
|
21
21
|
# Library path.
|
|
22
22
|
|
|
@@ -37,7 +37,7 @@ end
|
|
|
37
37
|
|
|
38
38
|
require 'nitro/context'
|
|
39
39
|
require 'nitro/controller'
|
|
40
|
-
require 'nitro/dispatcher
|
|
40
|
+
require 'nitro/dispatcher'
|
|
41
41
|
require 'nitro/render'
|
|
42
42
|
require 'nitro/server'
|
|
43
43
|
|
|
@@ -48,24 +48,31 @@ unless $NITRO_NO_ENVIRONMENT
|
|
|
48
48
|
# $NITRO_NO_ENVIRONMENT = true
|
|
49
49
|
#
|
|
50
50
|
# before requiring nitro.
|
|
51
|
+
|
|
52
|
+
# if $0 # mod_ruby set $0 to false
|
|
53
|
+
# Put the start file dir in the path.
|
|
54
|
+
Dir.chdir(File.dirname($0))
|
|
51
55
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
# Application code come here.
|
|
56
|
+
# Application code come here.
|
|
55
57
|
|
|
56
|
-
|
|
58
|
+
$LOAD_PATH.unshift 'src'
|
|
57
59
|
|
|
58
|
-
|
|
60
|
+
# Library code come here.
|
|
59
61
|
|
|
60
|
-
|
|
62
|
+
$LOAD_PATH.unshift 'lib'
|
|
63
|
+
# end
|
|
61
64
|
end
|
|
62
65
|
|
|
63
66
|
module Nitro
|
|
64
67
|
|
|
65
|
-
|
|
68
|
+
class << self
|
|
66
69
|
|
|
67
|
-
|
|
68
|
-
|
|
70
|
+
# A helper method to start a Nitro application.
|
|
71
|
+
|
|
72
|
+
def run(controller = nil)
|
|
73
|
+
Server.run(controller)
|
|
74
|
+
end
|
|
75
|
+
alias_method :start, :run
|
|
69
76
|
end
|
|
70
|
-
|
|
77
|
+
|
|
71
78
|
end
|
data/lib/nitro/adapter/cgi.rb
CHANGED
|
@@ -25,7 +25,9 @@ class Webrick
|
|
|
25
25
|
if RUBY_PLATFORM !~ /mswin32/
|
|
26
26
|
wblog = WEBrick::BasicLog::new('/dev/null')
|
|
27
27
|
elsif server.access_log
|
|
28
|
-
wblog = WEBrick::BasicLog::new(server.access_log
|
|
28
|
+
wblog = WEBrick::BasicLog::new(server.access_log)
|
|
29
|
+
elsif File.exist? 'log'
|
|
30
|
+
wblog = WEBrick::BasicLog::new('log/access.log')
|
|
29
31
|
else
|
|
30
32
|
wblog = STDERR
|
|
31
33
|
end
|
|
@@ -146,7 +148,7 @@ class WebrickAdapter < WEBrick::HTTPServlet::AbstractServlet
|
|
|
146
148
|
res.instance_variable_set(:@header, context.response_headers || {})
|
|
147
149
|
res.instance_variable_set(:@cookies, context.response_cookies || {})
|
|
148
150
|
res.body = context.out
|
|
149
|
-
res.chunked = true if context.out.is_a?(IO)
|
|
151
|
+
res.chunked = true if context.out.is_a?(IO) and context["SERVER_PROTOCOL"] == "HTTP/1.1"
|
|
150
152
|
|
|
151
153
|
context.close
|
|
152
154
|
ensure
|
data/lib/nitro/caching.rb
CHANGED
|
@@ -9,7 +9,8 @@ module Nitro
|
|
|
9
9
|
|
|
10
10
|
module Caching
|
|
11
11
|
|
|
12
|
-
# Action caching.
|
|
12
|
+
# Action caching. Caches a fragment, ie a page part.
|
|
13
|
+
# Use output cachingfor full page caching.
|
|
13
14
|
|
|
14
15
|
module Fragments
|
|
15
16
|
|
|
@@ -58,6 +59,11 @@ module Caching
|
|
|
58
59
|
end
|
|
59
60
|
end
|
|
60
61
|
|
|
62
|
+
#--
|
|
63
|
+
# gmosx: If you modify the code here, don't forget to modify
|
|
64
|
+
# the same method on the sweeper.
|
|
65
|
+
#++
|
|
66
|
+
|
|
61
67
|
def expire_fragment(name, options = {})
|
|
62
68
|
Fragments.store.delete(name, options)
|
|
63
69
|
end
|
data/lib/nitro/caching/output.rb
CHANGED
|
@@ -10,7 +10,7 @@ module Caching
|
|
|
10
10
|
|
|
11
11
|
module Output
|
|
12
12
|
|
|
13
|
-
def self.
|
|
13
|
+
def self.included(base) # :nodoc:
|
|
14
14
|
super
|
|
15
15
|
base.extend(ClassMethods)
|
|
16
16
|
base.module_eval do
|
|
@@ -57,6 +57,11 @@ module Caching
|
|
|
57
57
|
self.class.do_cache_output(@request.uri, @out)
|
|
58
58
|
end
|
|
59
59
|
end
|
|
60
|
+
|
|
61
|
+
#--
|
|
62
|
+
# If you change this method, don't forget the CacheSweeper
|
|
63
|
+
# expire method.
|
|
64
|
+
#++
|
|
60
65
|
|
|
61
66
|
def expire_output(name)
|
|
62
67
|
begin
|