nitro 0.29.0 → 0.30.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 +410 -0
- data/ProjectInfo +36 -44
- data/README +5 -5
- data/doc/AUTHORS +6 -0
- data/doc/RELEASES +159 -2
- data/lib/glue/sweeper.rb +2 -2
- data/lib/glue/webfile.rb +14 -1
- data/lib/nitro.rb +6 -9
- data/lib/nitro/adapter/mongrel.rb +36 -43
- data/lib/nitro/adapter/scgi.rb +1 -1
- data/lib/nitro/adapter/webrick.rb +96 -24
- data/lib/nitro/caching/actions.rb +2 -1
- data/lib/nitro/caching/fragments.rb +1 -8
- data/lib/nitro/caching/output.rb +14 -4
- data/lib/nitro/cgi.rb +19 -21
- data/lib/nitro/cgi/cookie.rb +5 -1
- data/lib/nitro/cgi/request.rb +20 -4
- data/lib/nitro/compiler.rb +74 -28
- data/lib/nitro/compiler/cleanup.rb +1 -1
- data/lib/nitro/compiler/elements.rb +1 -2
- data/lib/nitro/compiler/localization.rb +1 -1
- data/lib/nitro/compiler/markup.rb +1 -1
- data/lib/nitro/compiler/script.rb +52 -44
- data/lib/nitro/compiler/squeeze.rb +4 -3
- data/lib/nitro/compiler/xslt.rb +7 -6
- data/lib/nitro/context.rb +39 -20
- data/lib/nitro/controller.rb +24 -5
- data/lib/nitro/dispatcher.rb +13 -5
- data/lib/nitro/global.rb +63 -0
- data/lib/nitro/helper/feed.rb +432 -0
- data/lib/nitro/helper/form.rb +11 -3
- data/lib/nitro/helper/form/builder.rb +140 -0
- data/lib/nitro/helper/form/controls.rb +2 -1
- data/lib/nitro/helper/javascript.rb +6 -0
- data/lib/nitro/helper/javascript/morphing.rb +13 -6
- data/lib/nitro/helper/xhtml.rb +42 -6
- data/lib/nitro/helper/xml.rb +3 -0
- data/lib/nitro/part.rb +2 -2
- data/lib/nitro/render.rb +7 -2
- data/lib/nitro/router.rb +57 -16
- data/lib/nitro/scaffolding.rb +29 -20
- data/lib/nitro/server.rb +4 -10
- data/lib/nitro/server/drb.rb +1 -1
- data/lib/nitro/server/runner.rb +10 -0
- data/lib/nitro/session.rb +31 -12
- data/lib/nitro/session/drb.rb +13 -1
- data/lib/nitro/session/file.rb +1 -1
- data/lib/nitro/session/memcached.rb +1 -1
- data/lib/nitro/session/memory.rb +1 -1
- data/lib/nitro/session/og.rb +1 -1
- data/lib/nitro/test/testcase.rb +3 -0
- data/proto/public/error.xhtml +5 -5
- data/proto/public/js/controls.js +2 -2
- data/proto/public/js/dragdrop.js +320 -79
- data/proto/public/js/effects.js +200 -152
- data/proto/public/js/prototype.js +284 -63
- data/proto/public/js/scriptaculous.js +7 -5
- data/proto/public/js/unittest.js +11 -0
- data/proto/public/scaffold/advanced_search.xhtml +30 -0
- data/proto/public/scaffold/list.xhtml +8 -1
- data/proto/public/scaffold/search.xhtml +2 -1
- data/proto/script/scgi_service +1 -1
- data/src/part/admin/controller.rb +1 -1
- data/src/part/admin/skin.rb +1 -1
- data/test/nitro/CONFIG.rb +3 -0
- data/test/nitro/adapter/tc_webrick.rb +1 -1
- data/test/nitro/cgi/tc_cookie.rb +1 -1
- data/test/nitro/cgi/tc_request.rb +5 -5
- data/test/nitro/compiler/tc_client_morpher.rb +47 -0
- data/test/nitro/compiler/tc_compiler.rb +2 -0
- data/test/nitro/helper/tc_feed.rb +138 -0
- data/test/nitro/helper/tc_pager.rb +1 -1
- data/test/nitro/helper/tc_rss.rb +1 -1
- data/test/nitro/helper/tc_table.rb +1 -1
- data/test/nitro/helper/tc_xhtml.rb +1 -1
- data/test/nitro/tc_caching.rb +1 -1
- data/test/nitro/tc_cgi.rb +1 -1
- data/test/nitro/tc_context.rb +1 -1
- data/test/nitro/tc_controller.rb +31 -3
- data/test/nitro/tc_controller_aspect.rb +1 -1
- data/test/nitro/tc_dispatcher.rb +1 -1
- data/test/nitro/tc_element.rb +1 -1
- data/test/nitro/tc_flash.rb +1 -1
- data/test/nitro/tc_helper.rb +1 -1
- data/test/nitro/tc_render.rb +6 -6
- data/test/nitro/tc_router.rb +8 -4
- data/test/nitro/tc_server.rb +1 -3
- data/test/nitro/tc_session.rb +1 -3
- metadata +107 -104
- data/Rakefile +0 -232
- data/lib/nitro/adapter/acgi.rb +0 -237
- data/proto/public/Makefile.acgi +0 -40
- data/proto/public/acgi.c +0 -138
@@ -21,6 +21,8 @@ module Caching
|
|
21
21
|
|
22
22
|
module ClassMethods
|
23
23
|
|
24
|
+
# Cache the given actions.
|
25
|
+
|
24
26
|
def cache_action(*actions)
|
25
27
|
return unless caching_enabled?
|
26
28
|
|
@@ -49,7 +51,6 @@ module Caching
|
|
49
51
|
private
|
50
52
|
|
51
53
|
# Expire the cached fragment of the given actions.
|
52
|
-
#
|
53
54
|
#--
|
54
55
|
# FIXME: not very good implementation?
|
55
56
|
#++
|
@@ -17,14 +17,7 @@ module Caching
|
|
17
17
|
|
18
18
|
# The cache used to store the fragments.
|
19
19
|
|
20
|
-
setting :cache, :default =>
|
21
|
-
|
22
|
-
#--
|
23
|
-
# gmosx, FIXME: this is a hack, improve setting
|
24
|
-
# implementation.
|
25
|
-
#++
|
26
|
-
|
27
|
-
@@cache = Glue::MemoryCache.new
|
20
|
+
setting :cache, :default => Glue::MemoryCache.new, :doc => 'The cache used to store the fragments'
|
28
21
|
|
29
22
|
def self.get(name, options = {})
|
30
23
|
return @@cache.get(name, options)
|
data/lib/nitro/caching/output.rb
CHANGED
@@ -11,7 +11,8 @@ module Caching
|
|
11
11
|
# (Lighttpd, Apache, etc) for optimal performance.
|
12
12
|
#
|
13
13
|
# Nitro promotes coding your application in such a way as to
|
14
|
-
# allow for output caching to the greatest extend.
|
14
|
+
# allow for output caching to the greatest extend. Output
|
15
|
+
# caching *is your friend*.
|
15
16
|
#--
|
16
17
|
# gmosx, FIXME: Don't create excessive directories, use better
|
17
18
|
# rewrite rules to handle xxx.html files.
|
@@ -66,6 +67,9 @@ module Caching
|
|
66
67
|
end
|
67
68
|
end
|
68
69
|
|
70
|
+
# Explicitly expire the output cached under the given
|
71
|
+
# cache key. The cache key is typically the name of the
|
72
|
+
# top level action responsible for generating the page.
|
69
73
|
#--
|
70
74
|
# If you change this method, don't forget the CacheSweeper
|
71
75
|
# expire method.
|
@@ -73,14 +77,20 @@ module Caching
|
|
73
77
|
|
74
78
|
def expire_output(name)
|
75
79
|
begin
|
76
|
-
Logger.debug "Expirinig cache file '#{
|
77
|
-
FileUtils.rm_rf("#{
|
78
|
-
rescue Object
|
80
|
+
Logger.debug "Expirinig cache file '#{Server.public_root}/#{name}'" if $DBG
|
81
|
+
FileUtils.rm_rf("#{Server.public_root}/#{name}")
|
82
|
+
rescue Object => ex
|
79
83
|
# gmosx: is this the right thing to do?
|
80
84
|
end
|
81
85
|
end
|
82
86
|
alias_method :delete_output, :expire_output
|
83
87
|
|
88
|
+
# Is caching allowed for this action (page)? The default
|
89
|
+
# implementation does not cache post request or request
|
90
|
+
# with query parameters. You can work arround the second
|
91
|
+
# 'limitation' by cleverly using Nitro's implicit support
|
92
|
+
# for 'nice' urls.
|
93
|
+
|
84
94
|
def caching_allowed?
|
85
95
|
not (@request.post? or @request.uri =~ /\?/)
|
86
96
|
end
|
data/lib/nitro/cgi.rb
CHANGED
@@ -31,30 +31,28 @@ class Cgi
|
|
31
31
|
#--
|
32
32
|
# gmosx: only handle nitro requests.
|
33
33
|
#++
|
34
|
-
|
35
|
-
# gmosx: QUERY_STRING is sometimes not populated.
|
34
|
+
# gmosx: QUERY_STRING is sometimes not populated.
|
36
35
|
|
37
|
-
|
38
|
-
|
39
|
-
|
36
|
+
if context.query_string.empty? and context.uri =~ /\?/
|
37
|
+
context.headers['QUERY_STRING'] = context.uri.split('?').last
|
38
|
+
end
|
40
39
|
|
41
|
-
|
42
|
-
|
43
|
-
|
40
|
+
Cgi.parse_params(context)
|
41
|
+
Cgi.parse_cookies(context)
|
42
|
+
context.render(context.path)
|
44
43
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
end
|
55
|
-
else
|
56
|
-
out.print(context.out)
|
44
|
+
out.print(Cgi.response_headers(context))
|
45
|
+
|
46
|
+
if context.out.is_a?(IO)
|
47
|
+
begin
|
48
|
+
while buf = context.out.read(4096)
|
49
|
+
out.write(buf)
|
50
|
+
end
|
51
|
+
ensure
|
52
|
+
context.out.close
|
57
53
|
end
|
54
|
+
else
|
55
|
+
out.print(context.out)
|
58
56
|
end
|
59
57
|
|
60
58
|
$autoreload_dirty = false
|
@@ -116,7 +114,7 @@ class Cgi
|
|
116
114
|
if env['HTTP_COOKIE'] or env['COOKIE']
|
117
115
|
(env['HTTP_COOKIE'] or env['COOKIE']).split(/; /).each do |c|
|
118
116
|
key, val = c.split(/=/, 2)
|
119
|
-
|
117
|
+
val ||= ""
|
120
118
|
key = CGI.unescape(key)
|
121
119
|
val = val.split(/&/).collect{|v| CGI::unescape(v)}.join("\0")
|
122
120
|
|
data/lib/nitro/cgi/cookie.rb
CHANGED
@@ -18,14 +18,18 @@ class Cookie
|
|
18
18
|
@comment_url = @discard = @port = nil
|
19
19
|
end
|
20
20
|
|
21
|
+
# Set the cookie expiration.
|
22
|
+
|
21
23
|
def expires=(t)
|
22
24
|
@expires = t && (t.is_a?(Time) ? t.httpdate : t.to_s)
|
23
25
|
end
|
24
26
|
|
27
|
+
# When the cookie expires.
|
28
|
+
|
25
29
|
def expires
|
26
30
|
@expires && Time.parse(@expires)
|
27
31
|
end
|
28
|
-
|
32
|
+
|
29
33
|
def to_s
|
30
34
|
ret = ""
|
31
35
|
ret << @name << "=" << @value
|
data/lib/nitro/cgi/request.rb
CHANGED
@@ -26,6 +26,7 @@ module Request
|
|
26
26
|
# The request cookies.
|
27
27
|
|
28
28
|
attr_accessor :cookies
|
29
|
+
alias_method :cookie, :cookies
|
29
30
|
|
30
31
|
# The request protocol.
|
31
32
|
|
@@ -60,8 +61,8 @@ module Request
|
|
60
61
|
#
|
61
62
|
# === Examples
|
62
63
|
#
|
63
|
-
# www.
|
64
|
-
# www.
|
64
|
+
# www.nitroproject.org: request.domain # => 'nitroproject.org'
|
65
|
+
# www.nitroproject.co.uk: request.domain(2) # => 'nitroproject.co.uk'
|
65
66
|
|
66
67
|
def domain(tld_length = 1)
|
67
68
|
host.split('.').last(1 + tld_length).join('.')
|
@@ -71,7 +72,7 @@ module Request
|
|
71
72
|
#
|
72
73
|
# === Examples
|
73
74
|
#
|
74
|
-
# my.name.
|
75
|
+
# my.name.nitroproject.org: request.subdomains # => ['my', 'name']
|
75
76
|
|
76
77
|
def subdomains(tld_length = 1)
|
77
78
|
parts = host.split('.')
|
@@ -80,7 +81,7 @@ module Request
|
|
80
81
|
|
81
82
|
# The request query string.
|
82
83
|
#--
|
83
|
-
#
|
84
|
+
# gmosx, FIXME: handles some fcgi problems.
|
84
85
|
#++
|
85
86
|
|
86
87
|
def query_string
|
@@ -251,6 +252,20 @@ module Request
|
|
251
252
|
@params[param] = value
|
252
253
|
end
|
253
254
|
|
255
|
+
# Check if a boolean param (checkbox) is true.
|
256
|
+
|
257
|
+
def true?(param)
|
258
|
+
@params[param] == 'on'
|
259
|
+
end
|
260
|
+
alias_method :enabled?, :true?
|
261
|
+
alias_method :boolean, :true?
|
262
|
+
|
263
|
+
# Check if a boolean param (checkbox) is false.
|
264
|
+
|
265
|
+
def false?(param)
|
266
|
+
!true?(param)
|
267
|
+
end
|
268
|
+
|
254
269
|
# Fetch a parameter with default value.
|
255
270
|
|
256
271
|
def fetch(param, default = nil)
|
@@ -263,6 +278,7 @@ module Request
|
|
263
278
|
@params.has_key?(key)
|
264
279
|
end
|
265
280
|
alias_method :has_param?, :has_key?
|
281
|
+
alias_method :param?, :has_key?
|
266
282
|
end
|
267
283
|
|
268
284
|
end
|
data/lib/nitro/compiler.rb
CHANGED
@@ -40,6 +40,27 @@ class Compiler
|
|
40
40
|
|
41
41
|
setting :reload, :default => true, :doc => 'If true all code and templates are reloaded in each request'
|
42
42
|
|
43
|
+
|
44
|
+
# The default transformation pipeline. Nitro allows fine
|
45
|
+
# grained customization pipelines per controller or even per
|
46
|
+
# action. The Template transformation is added by default.
|
47
|
+
# Here come examples of pipeline customization:
|
48
|
+
#
|
49
|
+
# class MyController
|
50
|
+
# ann :self, :transformation_pipeline => [MyTransformer, AnotherXForm]
|
51
|
+
#
|
52
|
+
# ...
|
53
|
+
#
|
54
|
+
# def my_action
|
55
|
+
# ...
|
56
|
+
# end
|
57
|
+
# ann :my_action, :transformation_pipeline => Compiler.transformation_pipeline.dup.shift(CustomXForm)
|
58
|
+
#
|
59
|
+
# ...
|
60
|
+
# end
|
61
|
+
|
62
|
+
setting :transformation_pipeline, :default => [StaticInclude, Morphing, Elements, Markup, ScriptCompiler, Cleanup], :doc => 'The default transformation pipeline'
|
63
|
+
|
43
64
|
def initialize(controller = nil)
|
44
65
|
@controller = controller
|
45
66
|
@shared = {}
|
@@ -86,15 +107,34 @@ class Compiler
|
|
86
107
|
# The default transformation extracts the Ruby code from
|
87
108
|
# processing instructions, and uses the StaticInclude,
|
88
109
|
# Morphing, Elements and Markup compiler modules.
|
110
|
+
#
|
111
|
+
# The Template transformation stage is added by default.
|
112
|
+
#
|
113
|
+
# You can override this method or use aspects for really
|
114
|
+
# special transformation pipelines. Your imagination is the
|
115
|
+
# limit.
|
116
|
+
#--
|
117
|
+
# TODO: make Template stage pluggable.
|
118
|
+
# gmosx: This method is also called from the scaffolding
|
119
|
+
# code.
|
120
|
+
#++
|
89
121
|
|
90
|
-
def transform_template(template)
|
91
|
-
|
92
|
-
|
93
|
-
#
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
122
|
+
def transform_template(action, template)
|
123
|
+
# Check for an action specific transformation pipeline.
|
124
|
+
if (transformers = @controller.ann(action.to_sym).transformation_pipeline).nil?
|
125
|
+
# Check for a controller specific transformation pipeline.
|
126
|
+
if (transformers = @controller.ann.self.transformation_pipeline).nil?
|
127
|
+
# Use the default transformation pipeline.
|
128
|
+
transformers = Compiler.transformation_pipeline
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
transformers.each do |transformer|
|
133
|
+
template = transformer.transform(template, self)
|
134
|
+
end
|
135
|
+
|
136
|
+
# Add Template transformation stage by default.
|
137
|
+
|
98
138
|
template = Template.transform(template)
|
99
139
|
end
|
100
140
|
|
@@ -109,7 +149,7 @@ class Compiler
|
|
109
149
|
|
110
150
|
code = %{
|
111
151
|
def #{action}_template
|
112
|
-
#{transform_template(template)}
|
152
|
+
#{transform_template(action, template)}
|
113
153
|
end
|
114
154
|
}
|
115
155
|
|
@@ -155,14 +195,19 @@ class Compiler
|
|
155
195
|
#++
|
156
196
|
|
157
197
|
def compile_action(action)
|
158
|
-
action = action.to_s.gsub(/_action$/, '')
|
198
|
+
action = @action = action.to_s.gsub(/_action$/, '')
|
159
199
|
|
160
200
|
return false unless action
|
161
201
|
|
162
202
|
Logger.debug "Compiling action '#@controller##{action}'" if $DBG
|
163
203
|
|
164
204
|
valid = false
|
165
|
-
|
205
|
+
|
206
|
+
#--
|
207
|
+
# FIXME: parent_action_name does not work as expected,
|
208
|
+
# if you include actions from other controllers!!
|
209
|
+
#++
|
210
|
+
|
166
211
|
code = %{
|
167
212
|
def #{action}_action
|
168
213
|
@parent_action_name = @action_name
|
@@ -171,7 +216,7 @@ class Compiler
|
|
171
216
|
|
172
217
|
# Inject the pre advices.
|
173
218
|
|
174
|
-
code <<
|
219
|
+
code << ::Aspects.gen_advice_code(action, @controller.advices, :pre)
|
175
220
|
|
176
221
|
# Call the action
|
177
222
|
|
@@ -187,16 +232,16 @@ class Compiler
|
|
187
232
|
|
188
233
|
# Try to resolve action parameters. Returns negative
|
189
234
|
# numbers for arbitrary parameters.
|
235
|
+
#--
|
236
|
+
# gmosx: This needs a better implementation. Better means
|
237
|
+
# cleaner and more optimized code.
|
238
|
+
#++
|
190
239
|
|
191
240
|
param_count = @controller.instance_method(action.to_sym).arity
|
192
241
|
|
193
242
|
if param_count != 0
|
194
|
-
if param_count > 0
|
195
|
-
code << "params = Array.new(#{param_count}, nil);"
|
196
|
-
else
|
197
|
-
code << "params = [];"
|
198
|
-
end
|
199
243
|
code << %{
|
244
|
+
params = []
|
200
245
|
unless context.query_string.blank?
|
201
246
|
all_params = context.query_string.split(/[&;]/)
|
202
247
|
is_hash = all_params.first.index('=')
|
@@ -208,9 +253,16 @@ class Compiler
|
|
208
253
|
end
|
209
254
|
code << %{
|
210
255
|
break if qs.index('=') and not is_hash
|
211
|
-
params
|
256
|
+
params << CGI.unescape(qs.split(/=/).last || "")
|
212
257
|
end
|
213
258
|
end
|
259
|
+
|
260
|
+
# Concatenate some extracted parameters.
|
261
|
+
params.concat(context.params.values)
|
262
|
+
|
263
|
+
# Fill the array with nils for the missing params.
|
264
|
+
(#{param_count} - params.size).times { params << nil }
|
265
|
+
|
214
266
|
action_return_value = #{action}(*params)
|
215
267
|
}
|
216
268
|
else
|
@@ -267,7 +319,7 @@ class Compiler
|
|
267
319
|
|
268
320
|
# Inject the post advices.
|
269
321
|
|
270
|
-
code <<
|
322
|
+
code << ::Aspects.gen_advice_code(action, @controller.advices, :post)
|
271
323
|
|
272
324
|
code << %{
|
273
325
|
@action_name = @parent_action_name
|
@@ -279,6 +331,8 @@ class Compiler
|
|
279
331
|
@controller.class_eval(code)
|
280
332
|
|
281
333
|
unless @controller.respond_to?("#{action}_template")
|
334
|
+
# If there is not method {action}_template in the controller
|
335
|
+
# search for a file template.
|
282
336
|
if template_path
|
283
337
|
compile_template(action, template_path)
|
284
338
|
end
|
@@ -297,15 +351,6 @@ class Compiler
|
|
297
351
|
# :section: Helper methods.
|
298
352
|
|
299
353
|
class << self
|
300
|
-
# Helper method for manipulating the template transformation
|
301
|
-
# pipeline.
|
302
|
-
|
303
|
-
def setup_transform_template(&block)
|
304
|
-
send :define_method, :transform_template, block
|
305
|
-
end
|
306
|
-
alias_method :setup_template_transform, :setup_transform_template
|
307
|
-
alias_method :setup_template_transformation, :setup_transform_template
|
308
|
-
|
309
354
|
# Typically used to precompile css templates.
|
310
355
|
|
311
356
|
def precompile(filename)
|
@@ -330,3 +375,4 @@ end
|
|
330
375
|
# * George Moschovitis <gm@navel.gr>
|
331
376
|
# * Chris Farmiloe <chris.farmiloe@farmiloe.com>
|
332
377
|
# * Rob Pitt <rob@motionpath.co.uk>
|
378
|
+
# * Jonas Pfenniger <zimba.tm@gmail.com>
|
@@ -80,7 +80,7 @@ class Elements # :nodoc: all
|
|
80
80
|
# name = name.demodulize
|
81
81
|
return false unless name =~ PREFIX_RE or name =~ CAPITALIZED_RE
|
82
82
|
|
83
|
-
name = name.gsub(
|
83
|
+
name = name.gsub(PREFIX_RE,'').camelize if name =~ PREFIX_RE
|
84
84
|
|
85
85
|
# First try to use Nitro::Element::xxx then ::xxx
|
86
86
|
|
@@ -95,7 +95,6 @@ class Elements # :nodoc: all
|
|
95
95
|
namespace = @compiler.controller.name
|
96
96
|
if /::/ =~ namespace
|
97
97
|
namespace = namespace.gsub( /::[a-zA-Z]+$/, "::#{name}" )
|
98
|
-
pp namespace
|
99
98
|
klass = Class.by_name(namespace)
|
100
99
|
end
|
101
100
|
rescue
|