nitro 0.20.0 → 0.21.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 +752 -543
- data/INSTALL +38 -38
- data/README +264 -225
- data/Rakefile +48 -49
- data/bin/nitro +3 -3
- data/bin/nitrogen +6 -6
- data/doc/AUTHORS +10 -10
- data/doc/CHANGELOG.1 +1939 -1939
- data/doc/CHANGELOG.2 +954 -954
- data/doc/LICENSE +3 -3
- data/doc/MIGRATION +28 -0
- data/doc/RELEASES +814 -643
- data/doc/config.txt +5 -5
- data/install.rb +7 -17
- data/lib/nitro.rb +38 -9
- data/lib/nitro/adapter/cgi.rb +311 -312
- data/lib/nitro/adapter/fastcgi.rb +18 -25
- data/lib/nitro/adapter/webrick.rb +128 -137
- data/lib/nitro/adapter/wee.rb +51 -0
- data/lib/nitro/caching.rb +20 -20
- data/lib/nitro/caching/actions.rb +43 -43
- data/lib/nitro/caching/fragments.rb +46 -46
- data/lib/nitro/caching/invalidation.rb +11 -11
- data/lib/nitro/caching/output.rb +65 -65
- data/lib/nitro/caching/stores.rb +67 -67
- data/lib/nitro/compiler.rb +262 -0
- data/lib/nitro/compiler/elements.rb +0 -0
- data/lib/nitro/compiler/errors.rb +65 -0
- data/lib/nitro/compiler/localization.rb +25 -0
- data/lib/nitro/compiler/markup.rb +19 -0
- data/lib/nitro/compiler/shaders.rb +206 -0
- data/lib/nitro/compiler/squeeze.rb +20 -0
- data/lib/nitro/compiler/xslt.rb +61 -0
- data/lib/nitro/context.rb +87 -88
- data/lib/nitro/controller.rb +151 -158
- data/lib/nitro/cookie.rb +34 -34
- data/lib/nitro/dispatcher.rb +195 -186
- data/lib/nitro/element.rb +132 -126
- data/lib/nitro/element/java_script.rb +6 -6
- data/lib/nitro/flash.rb +66 -66
- data/lib/nitro/mail.rb +192 -192
- data/lib/nitro/mixin/buffer.rb +66 -0
- data/lib/nitro/mixin/debug.rb +16 -16
- data/lib/nitro/mixin/form.rb +88 -0
- data/lib/nitro/mixin/helper.rb +2 -2
- data/lib/nitro/mixin/javascript.rb +108 -108
- data/lib/nitro/mixin/markup.rb +144 -0
- data/lib/nitro/mixin/pager.rb +202 -202
- data/lib/nitro/mixin/rss.rb +67 -0
- data/lib/nitro/mixin/table.rb +63 -0
- data/lib/nitro/mixin/xhtml.rb +75 -0
- data/lib/nitro/mixin/xml.rb +124 -0
- data/lib/nitro/render.rb +183 -359
- data/lib/nitro/request.rb +140 -140
- data/lib/nitro/response.rb +27 -27
- data/lib/nitro/routing.rb +21 -21
- data/lib/nitro/scaffold.rb +124 -118
- data/lib/nitro/server.rb +117 -80
- data/lib/nitro/server/runner.rb +341 -0
- data/lib/nitro/service.rb +12 -12
- data/lib/nitro/service/xmlrpc.rb +22 -22
- data/lib/nitro/session.rb +122 -120
- data/lib/nitro/session/drb.rb +9 -9
- data/lib/nitro/session/drbserver.rb +34 -34
- data/lib/nitro/template.rb +171 -155
- data/lib/nitro/testing/assertions.rb +90 -90
- data/lib/nitro/testing/context.rb +16 -16
- data/lib/nitro/testing/testcase.rb +34 -34
- data/proto/conf/lhttpd.conf +9 -9
- data/proto/public/error.xhtml +75 -75
- data/proto/public/index.xhtml +18 -18
- data/proto/public/js/behaviour.js +65 -65
- data/proto/public/js/controls.js +1 -1
- data/proto/public/js/prototype.js +3 -3
- data/proto/public/settings.xhtml +61 -61
- data/proto/run.rb +1 -5
- data/test/nitro/adapter/raw_post1.bin +0 -0
- data/test/nitro/adapter/tc_cgi.rb +57 -57
- data/test/nitro/adapter/tc_webrick.rb +4 -4
- data/test/nitro/mixin/tc_pager.rb +25 -25
- data/test/nitro/mixin/tc_rss.rb +24 -0
- data/test/nitro/mixin/tc_table.rb +31 -0
- data/test/nitro/mixin/tc_xhtml.rb +13 -0
- data/test/nitro/tc_caching.rb +10 -10
- data/test/nitro/tc_context.rb +8 -8
- data/test/nitro/tc_controller.rb +48 -48
- data/test/nitro/tc_cookie.rb +6 -6
- data/test/nitro/tc_dispatcher.rb +64 -64
- data/test/nitro/tc_element.rb +27 -27
- data/test/nitro/tc_flash.rb +31 -31
- data/test/nitro/tc_mail.rb +63 -63
- data/test/nitro/tc_server.rb +26 -26
- data/test/nitro/tc_session.rb +9 -9
- data/test/nitro/tc_template.rb +19 -19
- data/test/public/blog/list.xhtml +1 -1
- metadata +31 -37
- data/lib/nitro/buffering.rb +0 -45
- data/lib/nitro/builder/form.rb +0 -104
- data/lib/nitro/builder/rss.rb +0 -104
- data/lib/nitro/builder/table.rb +0 -80
- data/lib/nitro/builder/xhtml.rb +0 -132
- data/lib/nitro/builder/xml.rb +0 -131
- data/lib/nitro/conf.rb +0 -36
- data/lib/nitro/environment.rb +0 -21
- data/lib/nitro/errors.rb +0 -69
- data/lib/nitro/localization.rb +0 -153
- data/lib/nitro/markup.rb +0 -147
- data/lib/nitro/output.rb +0 -24
- data/lib/nitro/runner.rb +0 -348
- data/lib/nitro/shaders.rb +0 -206
- data/test/nitro/builder/tc_rss.rb +0 -23
- data/test/nitro/builder/tc_table.rb +0 -30
- data/test/nitro/builder/tc_xhtml.rb +0 -39
- data/test/nitro/builder/tc_xml.rb +0 -56
- data/test/nitro/tc_localization.rb +0 -49
data/lib/nitro/request.rb
CHANGED
|
@@ -1,163 +1,163 @@
|
|
|
1
1
|
module Nitro
|
|
2
|
-
|
|
2
|
+
|
|
3
3
|
# Encapsulates a request. This is an abstract request
|
|
4
4
|
# typically extended by sub-classes. This module
|
|
5
5
|
# is included in Context
|
|
6
6
|
|
|
7
7
|
module Request
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
# The request input stream.
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
attr_accessor :in
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
# The request headers collection. Also called
|
|
14
|
+
# the request environment (env).
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
16
|
+
attr_accessor :headers
|
|
17
|
+
alias_method :env, :headers
|
|
18
|
+
alias_method :env=, :headers=
|
|
19
|
+
# for compatibility with cgi.rb
|
|
20
|
+
alias_method :env_table, :headers
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
# The parsed query parameters collection.
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
attr_accessor :params
|
|
25
|
+
alias_method :query, :params
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
# The request cookies.
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
attr_accessor :cookies
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
# The request protocol.
|
|
32
32
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
def protocol
|
|
34
|
+
443 == port ? 'https://' : 'http://'
|
|
35
|
+
end
|
|
36
36
|
|
|
37
|
-
|
|
37
|
+
# Is this an ssl request?
|
|
38
38
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
39
|
+
def ssl?
|
|
40
|
+
443 == port
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# The request uri.
|
|
44
|
+
|
|
45
|
+
def uri
|
|
46
|
+
@headers['REQUEST_URI']
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# The path is the uri without the query string.
|
|
50
50
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
51
|
+
def path
|
|
52
|
+
path = uri ? uri.split('?').first : ''
|
|
53
|
+
end
|
|
54
54
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
55
|
+
def path_info
|
|
56
|
+
@headers['PATH_INFO']
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# The request query string.
|
|
60
|
+
|
|
61
|
+
def query_string
|
|
62
|
+
@headers['QUERY_STRING']
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# The request method.
|
|
66
|
+
|
|
67
|
+
def method
|
|
68
|
+
@headers['REQUEST_METHOD'].downcase.intern
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# Is this a post method?
|
|
72
|
+
|
|
73
|
+
def post?
|
|
74
|
+
method == :post
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# Return the referer. For the initial page in the
|
|
78
|
+
# clickstream there is no referer, set "/" by default.
|
|
79
|
+
|
|
80
|
+
def referer
|
|
81
|
+
return @headers['HTTP_REFERER'] || '/'
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# The content_length
|
|
85
|
+
|
|
86
|
+
def content_length
|
|
87
|
+
return @headers['CONTENT_LENGTH'].to_i
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# The remote IP address. REMOTE_ADDR is the standard
|
|
91
|
+
# but will fail if the user is behind a proxy.
|
|
92
|
+
# HTTP_CLIENT_IP and/or HTTP_X_FORWARDED_FOR are set by
|
|
93
|
+
# proxies so check for these before falling back to
|
|
94
|
+
# REMOTE_ADDR. HTTP_X_FORWARDED_FOR may be a comma-delimited
|
|
95
|
+
# list in the case of multiple chained proxies; the first
|
|
96
|
+
# is the originating IP.
|
|
97
|
+
|
|
98
|
+
def remote_ip
|
|
99
|
+
return @headers['HTTP_CLIENT_IP'] if @headers.include?('HTTP_CLIENT_IP')
|
|
100
|
+
|
|
101
|
+
if @headers.include?('HTTP_X_FORWARDED_FOR') then
|
|
102
|
+
remote_ips = @headers['HTTP_X_FORWARDED_FOR'].split(',').reject do |ip|
|
|
103
|
+
ip =~ /^unknown$|^(10|172\.16|192\.168)\./i
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
return remote_ips.first.strip unless remote_ips.empty?
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
return @headers['REMOTE_ADDR']
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
# The server port.
|
|
113
|
+
|
|
114
|
+
def port
|
|
115
|
+
@headers['SERVER_PORT'].to_i
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
# The server host name.
|
|
119
|
+
# Also handles proxy forwarding.
|
|
120
|
+
|
|
121
|
+
def host
|
|
122
|
+
@headers['HTTP_X_FORWARDED_HOST'] || @headers['HTTP_HOST']
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def host_url
|
|
126
|
+
"http://#{host}"
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# The raw data of the request.
|
|
130
|
+
# Useful to implement Webservices.
|
|
131
|
+
#--
|
|
132
|
+
# FIXME: better name and implementation.
|
|
133
|
+
#++
|
|
134
|
+
|
|
135
|
+
def raw_body
|
|
136
|
+
unless @raw_body
|
|
137
|
+
@in.rewind
|
|
138
|
+
@raw_body = @in.read(content_length)
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
@raw_body
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
# Lookup a query parameter.
|
|
145
|
+
|
|
146
|
+
def [](param)
|
|
147
|
+
@params[param]
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
# Set a query parameter.
|
|
151
|
+
|
|
152
|
+
def []=(param, value)
|
|
153
|
+
@params[param] = value
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
# Fetch a parameter with default value.
|
|
157
|
+
|
|
158
|
+
def fetch(param, default = nil)
|
|
159
|
+
@params.fetch(param, default)
|
|
160
|
+
end
|
|
161
161
|
end
|
|
162
162
|
|
|
163
163
|
end
|
data/lib/nitro/response.rb
CHANGED
|
@@ -1,42 +1,42 @@
|
|
|
1
1
|
module Nitro
|
|
2
|
-
|
|
2
|
+
|
|
3
3
|
# HTTP Response. This module is included in Context.
|
|
4
4
|
|
|
5
5
|
module Response
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
# The Response status.
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
attr_accessor :status
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
# The Response headers.
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
attr_accessor :response_headers
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
# The Response cookies.
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
attr_accessor :response_cookies
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
def content_type=(ctype)
|
|
20
|
+
@response_headers['Content-Type'] = ctype
|
|
21
|
+
end
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
23
|
+
# Add a cookie to the response. Better use this
|
|
24
|
+
# method to avoid precreating the cookies array
|
|
25
|
+
# for every request.
|
|
26
|
+
#
|
|
27
|
+
# === Examples
|
|
28
|
+
#
|
|
29
|
+
# add_cookie('nsid', 'gmosx')
|
|
30
|
+
# add_cookie(Cookie.new('nsid', 'gmosx')
|
|
31
|
+
|
|
32
|
+
def add_cookie(cookie, value = nil)
|
|
33
|
+
if value
|
|
34
|
+
(@response_cookies ||= []) << Cookie.new(cookie, value)
|
|
35
|
+
else
|
|
36
|
+
(@response_cookies ||= []) << cookie
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
alias_method :send_cookie, :add_cookie
|
|
40
40
|
|
|
41
41
|
end
|
|
42
42
|
|
data/lib/nitro/routing.rb
CHANGED
|
@@ -3,28 +3,28 @@ module Nitro
|
|
|
3
3
|
# Router mixin. Typically used to generate 'nice' urls.
|
|
4
4
|
# Nice urls are considered (?) more Search Engine
|
|
5
5
|
# friendly.
|
|
6
|
-
|
|
6
|
+
|
|
7
7
|
module Router
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
8
|
+
|
|
9
|
+
# The route table maps 'nice URLs' to real URLs that
|
|
10
|
+
# can be handled by the Dispatcher.
|
|
11
|
+
|
|
12
|
+
attr_accessor :routes
|
|
13
|
+
|
|
14
|
+
# Apply routing rules to the path.
|
|
15
|
+
|
|
16
|
+
def route(path, context)
|
|
17
|
+
for rule, real_path, *params in @routes
|
|
18
|
+
if md = path.match(rule)
|
|
19
|
+
params.each_with_index do |p, idx|
|
|
20
|
+
context[p] = md.captures[idx]
|
|
21
|
+
end
|
|
22
|
+
return real_path
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
return path
|
|
27
|
+
end
|
|
28
28
|
|
|
29
29
|
end
|
|
30
30
|
|
data/lib/nitro/scaffold.rb
CHANGED
|
@@ -2,9 +2,13 @@ require 'facet/string/singular'
|
|
|
2
2
|
require 'facet/string/demodulize'
|
|
3
3
|
require 'facet/string/underscore'
|
|
4
4
|
|
|
5
|
+
require 'nitro/compiler'
|
|
6
|
+
|
|
5
7
|
module Nitro
|
|
6
8
|
|
|
7
9
|
# The scaffolder adds default actions to a Controller.
|
|
10
|
+
#
|
|
11
|
+
# WARNING: This code is slightly outdated.
|
|
8
12
|
#--
|
|
9
13
|
# FIXME: handle controller base in generated routes.
|
|
10
14
|
# FIXME: better handle templates (check if action exists).
|
|
@@ -12,124 +16,126 @@ module Nitro
|
|
|
12
16
|
|
|
13
17
|
module Scaffolding
|
|
14
18
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
19
|
+
def self.append_features(base) # :nodoc:
|
|
20
|
+
super
|
|
21
|
+
base.extend(ClassMethods)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
module ClassMethods
|
|
25
|
+
|
|
26
|
+
# Enchant the caller with a number of default methods.
|
|
27
|
+
# Override the automatically generated methods as needed.
|
|
28
|
+
|
|
29
|
+
def scaffold(klass, options = {})
|
|
30
|
+
compiler = Compiler.new
|
|
31
|
+
|
|
32
|
+
oid = options[:oid] || 'oid'
|
|
33
|
+
name = options[:name] || klass.to_s.demodulize.underscore.downcase
|
|
34
|
+
list_name = options[:list_name] || name.plural
|
|
35
|
+
options[:nosuffix] ? suffix = nil : suffix = "_#{name}"
|
|
36
|
+
|
|
37
|
+
# Add methods to the scaffolded class.
|
|
38
|
+
|
|
39
|
+
klass.module_eval %{
|
|
40
|
+
def to_href
|
|
41
|
+
"view#{suffix}?oid=\#\{@oid\}"
|
|
42
|
+
# "view#{suffix}/\#\{@oid\}"
|
|
43
|
+
end
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
# Add methods to the service.
|
|
47
|
+
|
|
48
|
+
code = ''
|
|
49
|
+
|
|
50
|
+
if options[:index]
|
|
51
|
+
code << %{
|
|
52
|
+
def index
|
|
53
|
+
list#{suffix}
|
|
54
|
+
end
|
|
55
|
+
}
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
code << %{
|
|
59
|
+
def new#{suffix}
|
|
60
|
+
@#{name} = #{klass}.new
|
|
61
|
+
render '/form#{suffix}'
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def edit#{suffix}
|
|
65
|
+
@#{name} = #{klass}[request['oid']]
|
|
66
|
+
render '/form#{suffix}'
|
|
67
|
+
end
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
unless compiler.template_for_action("form#{suffix}", self.template_root)
|
|
71
|
+
code << %{
|
|
72
|
+
def form#{suffix}
|
|
73
|
+
o << %|
|
|
74
|
+
<html>
|
|
75
|
+
<form action="save#{suffix}" method="post">
|
|
76
|
+
|
|
|
77
|
+
if @#{name}.oid
|
|
78
|
+
o << %|
|
|
79
|
+
<input type="hidden" name="oid" value="\#\{@#{name}\}" />
|
|
80
|
+
|
|
|
81
|
+
end
|
|
82
|
+
o.build_form(@#{name})
|
|
83
|
+
o << %|
|
|
84
|
+
<input type="submit" value="Save" />
|
|
85
|
+
</form>
|
|
86
|
+
</html>
|
|
87
|
+
|
|
|
88
|
+
end
|
|
89
|
+
}
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
code << %{
|
|
93
|
+
# TODO: add pager support here!
|
|
94
|
+
|
|
95
|
+
def list#{suffix}
|
|
96
|
+
@#{list_name} = #{klass}.all('ORDER BY oid')
|
|
97
|
+
}
|
|
98
|
+
unless compiler.template_for_action("list#{suffix}", self.template_root)
|
|
99
|
+
code << %{
|
|
100
|
+
o.ul {
|
|
101
|
+
for item in @#{list_name}
|
|
102
|
+
o.li(item.to_s)
|
|
103
|
+
end
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
end
|
|
107
|
+
code << %{
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def view#{suffix}
|
|
111
|
+
# @#{name} = #{klass}[@context['#{oid}']]
|
|
112
|
+
@#{name} = #{klass}[@#{oid}]
|
|
113
|
+
end
|
|
114
|
+
action :view#{suffix}, :route => \%r\{#{@base}/view#{suffix}/(.*)\}, 'oid' => 1
|
|
115
|
+
|
|
116
|
+
def save#{suffix}
|
|
117
|
+
if oid = request['oid']
|
|
118
|
+
@#{name} = request.fill(#{klass}[oid])
|
|
119
|
+
else
|
|
120
|
+
@#{name} = request.fill(#{klass}.new)
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
@#{name}.save
|
|
124
|
+
|
|
125
|
+
redirect 'list#{suffix}'
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def del#{suffix}
|
|
129
|
+
#{klass}.delete(@context['#{oid}'])
|
|
130
|
+
redirect_referer
|
|
131
|
+
end
|
|
132
|
+
alias_method :delete#{suffix}, :del#{suffix}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
class_eval(code)
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
end
|
|
133
139
|
|
|
134
140
|
end
|
|
135
141
|
|