nitro 0.8.0 → 0.9.3
Sign up to get free protection for your applications and to get access to all the features.
- data/AUTHORS +3 -4
- data/ChangeLog +418 -0
- data/LICENSE +1 -1
- data/README +157 -89
- data/RELEASES +50 -0
- data/Rakefile +5 -7
- data/benchmark/nitro/bench.rb +5 -0
- data/benchmark/nitro/simple-webrick-n-200.txt +44 -0
- data/benchmark/nitro/static-webrick-n-200.txt +43 -0
- data/benchmark/nitro/tiny-lhttpd-n-200-c-5.txt +43 -0
- data/benchmark/nitro/tiny-webrick-n-200-c-5.txt +44 -0
- data/benchmark/nitro/tiny-webrick-n-200.txt +44 -0
- data/benchmark/nitro/tiny2-webrick-n-200.txt +44 -0
- data/{lib/nitro/server/cluster.rb → bin/cluster} +26 -30
- data/bin/proto/README +2 -2
- data/bin/proto/{apache.conf → conf/apache.conf} +0 -0
- data/bin/proto/conf/app.conf.rb +22 -0
- data/bin/proto/conf/lhttpd.conf +236 -0
- data/bin/proto/ctl +4 -0
- data/bin/proto/lib/README +5 -0
- data/bin/proto/log/README +3 -0
- data/bin/proto/root/fcgi.rb +6 -0
- data/bin/proto/root/index.xhtml +65 -7
- data/bin/proto/root/m/nitro.png +0 -0
- data/examples/blog/README +7 -5
- data/examples/blog/{apache.conf → conf/apache.conf} +0 -0
- data/examples/blog/conf/app.conf.rb +56 -0
- data/examples/blog/conf/lhttpd.conf +236 -0
- data/examples/blog/ctl +4 -0
- data/examples/blog/lib/blog.rb +11 -136
- data/examples/blog/lib/blog/controller.rb +99 -0
- data/examples/blog/lib/blog/model.rb +39 -0
- data/examples/blog/log/README +3 -0
- data/examples/blog/root/comments.xhtml +2 -2
- data/examples/blog/root/fcgi.rb +6 -0
- data/examples/blog/root/index.xhtml +4 -5
- data/examples/blog/root/login.xhtml +2 -2
- data/examples/blog/root/style.xsl +9 -9
- data/examples/blog/root/view_entry.xhtml +2 -2
- data/examples/flash/conf/app.conf.rb +23 -0
- data/examples/flash/ctl +4 -0
- data/examples/flash/log/README +3 -0
- data/examples/flash/root/index.xhtml +0 -9
- data/examples/flash/root/show_inline_text.xhtml +10 -5
- data/examples/no_xsl_blog/README +12 -0
- data/examples/no_xsl_blog/conf/apache.conf +0 -0
- data/examples/no_xsl_blog/conf/app.conf.rb +57 -0
- data/examples/no_xsl_blog/conf/lhttpd.conf +236 -0
- data/examples/no_xsl_blog/ctl +4 -0
- data/examples/no_xsl_blog/lib/blog.rb +20 -0
- data/examples/no_xsl_blog/lib/blog/controller.rb +102 -0
- data/examples/no_xsl_blog/lib/blog/model.rb +39 -0
- data/examples/no_xsl_blog/lib/blog/template.rb +134 -0
- data/examples/no_xsl_blog/log/README +3 -0
- data/examples/no_xsl_blog/root/comments.xhtml +41 -0
- data/examples/no_xsl_blog/root/entry_form.xhtml +22 -0
- data/examples/no_xsl_blog/root/fcgi.rb +6 -0
- data/examples/no_xsl_blog/root/index.xhtml +39 -0
- data/examples/no_xsl_blog/root/login.xhtml +21 -0
- data/examples/no_xsl_blog/root/m/bubbles.gif +0 -0
- data/examples/no_xsl_blog/root/m/comments_curve.gif +0 -0
- data/examples/no_xsl_blog/root/m/down.gif +0 -0
- data/examples/no_xsl_blog/root/m/footer_bg.gif +0 -0
- data/examples/no_xsl_blog/root/m/garrow.gif +0 -0
- data/examples/no_xsl_blog/root/m/gbull.gif +0 -0
- data/examples/no_xsl_blog/root/m/grbull.gif +0 -0
- data/examples/no_xsl_blog/root/m/h1_bg.gif +0 -0
- data/examples/no_xsl_blog/root/m/header_bg.gif +0 -0
- data/examples/no_xsl_blog/root/m/nitro.gif +0 -0
- data/examples/no_xsl_blog/root/m/obull.gif +0 -0
- data/examples/no_xsl_blog/root/m/page_bg.gif +0 -0
- data/examples/no_xsl_blog/root/m/rss.gif +0 -0
- data/examples/no_xsl_blog/root/m/side_title_bg.gif +0 -0
- data/examples/no_xsl_blog/root/m/sidebar_bg.gif +0 -0
- data/examples/no_xsl_blog/root/recent_posts.xhtml +14 -0
- data/examples/no_xsl_blog/root/style.css +301 -0
- data/examples/no_xsl_blog/root/view_entry.xhtml +25 -0
- data/examples/no_xsl_blog/root/view_entry.xml +12 -0
- data/examples/og/run.rb +2 -2
- data/examples/tiny/README +2 -2
- data/examples/tiny/conf/apache.conf +5 -0
- data/examples/tiny/conf/app.conf.rb +21 -0
- data/examples/tiny/conf/lhttpd.conf +236 -0
- data/examples/tiny/ctl +4 -0
- data/examples/tiny/log/README +3 -0
- data/examples/tiny/root/fcgi.rb +6 -0
- data/examples/tiny/root/index.xhtml +7 -4
- data/examples/tiny/root/nitro.png +0 -0
- data/lib/glue.rb +13 -9
- data/lib/glue/array.rb +1 -1
- data/lib/glue/cache.rb +1 -1
- data/lib/glue/flexob.rb +12 -0
- data/lib/glue/hash.rb +1 -1
- data/lib/glue/inflector.rb +2 -2
- data/lib/glue/logger.rb +4 -8
- data/lib/glue/misc.rb +14 -0
- data/lib/glue/number.rb +1 -1
- data/lib/glue/object.rb +26 -0
- data/lib/glue/pool.rb +1 -1
- data/lib/glue/property.rb +84 -91
- data/lib/glue/string.rb +1 -1
- data/lib/glue/time.rb +1 -1
- data/lib/glue/validation.rb +1 -1
- data/lib/nitro.rb +18 -6
- data/lib/nitro/adaptors/cgi.rb +291 -0
- data/lib/nitro/adaptors/fastcgi.rb +42 -0
- data/lib/nitro/adaptors/runner.rb +123 -0
- data/lib/nitro/adaptors/webrick.rb +110 -0
- data/lib/nitro/buffering.rb +43 -0
- data/lib/nitro/builders/form.rb +1 -1
- data/lib/nitro/builders/rss.rb +1 -1
- data/{bin → lib/nitro}/cluster.rb +26 -30
- data/lib/nitro/context.rb +82 -0
- data/lib/nitro/controller.rb +50 -0
- data/lib/nitro/cookie.rb +46 -0
- data/lib/nitro/dispatcher.rb +105 -0
- data/lib/nitro/filters.rb +9 -10
- data/lib/nitro/localization.rb +42 -0
- data/lib/nitro/mail.rb +11 -14
- data/lib/nitro/render.rb +275 -0
- data/lib/nitro/request.rb +128 -0
- data/lib/nitro/response.rb +38 -0
- data/lib/nitro/scaffold.rb +11 -11
- data/lib/nitro/session.rb +84 -0
- data/lib/nitro/{server/shaders.rb → shaders.rb} +56 -36
- data/lib/nitro/ui/pager.rb +23 -26
- data/lib/nitro/{sitemap.rb → ui/sitemap.rb} +4 -12
- data/lib/nitro/uri.rb +1 -1
- data/lib/nitro/version.rb +10 -8
- data/lib/og.rb +66 -65
- data/lib/og/backend.rb +1 -1
- data/lib/og/backends/mysql.rb +48 -52
- data/lib/og/backends/psql.rb +34 -37
- data/lib/og/connection.rb +15 -15
- data/lib/og/enchant.rb +16 -9
- data/lib/og/meta.rb +127 -54
- data/lib/og/mock.rb +18 -18
- data/lib/og/version.rb +6 -4
- data/lib/parts/content.rb +4 -8
- data/test/glue/tc_logger.rb +3 -0
- data/test/glue/tc_property.rb +19 -3
- data/test/nitro/adaptors/tc_cgi.rb +63 -0
- data/test/nitro/adaptors/tc_webrick.rb +15 -0
- data/test/nitro/builders/tc_xml.rb +2 -2
- data/test/nitro/tc_context.rb +13 -0
- data/test/nitro/tc_controller.rb +47 -0
- data/test/nitro/tc_dispatcher.rb +64 -0
- data/test/nitro/tc_session.rb +20 -0
- data/test/nitro/{tc_sitemap.rb → ui/tc_sitemap.rb} +1 -1
- data/test/root/blog/list.xhtml +6 -0
- data/test/tc_og.rb +41 -4
- metadata +115 -59
- data/bin/proto/app.rb +0 -20
- data/bin/proto/config.rb +0 -77
- data/examples/blog/app.rb +0 -21
- data/examples/blog/config.rb +0 -95
- data/examples/blog/env.rb +0 -22
- data/examples/flash/README +0 -34
- data/examples/flash/app.rb +0 -20
- data/examples/flash/config.rb +0 -38
- data/examples/flash/lib/flash.rb +0 -40
- data/examples/flash/tmp.swf +0 -0
- data/examples/tiny/app.rb +0 -19
- data/examples/tiny/config.rb +0 -29
- data/examples/tiny/root/nitro-small.png +0 -0
- data/lib/nitro/application.rb +0 -217
- data/lib/nitro/config.rb +0 -128
- data/lib/nitro/events.rb +0 -122
- data/lib/nitro/html.rb +0 -151
- data/lib/nitro/http.rb +0 -102
- data/lib/nitro/l10n.rb +0 -30
- data/lib/nitro/server.rb +0 -59
- data/lib/nitro/server/appserver.rb +0 -67
- data/lib/nitro/server/cookie.rb +0 -87
- data/lib/nitro/server/dispatcher.rb +0 -62
- data/lib/nitro/server/filters.rb +0 -75
- data/lib/nitro/server/filters/autologin.rb +0 -51
- data/lib/nitro/server/fragment.rb +0 -70
- data/lib/nitro/server/handlers.rb +0 -127
- data/lib/nitro/server/render.rb +0 -426
- data/lib/nitro/server/request.rb +0 -658
- data/lib/nitro/server/requestpart.rb +0 -54
- data/lib/nitro/server/script.rb +0 -387
- data/lib/nitro/server/server.rb +0 -57
- data/lib/nitro/server/session.rb +0 -220
- data/lib/nitro/server/user.rb +0 -46
- data/lib/nitro/server/webrick.rb +0 -180
- data/lib/nitro/service.rb +0 -26
- data/lib/xsl/ui.xsl +0 -51
- data/lib/xsl/xforms.xsl +0 -28
- data/test/nitro/server/tc_cookie.rb +0 -34
- data/test/nitro/server/tc_filters.rb +0 -38
- data/test/nitro/server/tc_request.rb +0 -70
- data/test/nitro/server/tc_requestpart.rb +0 -28
- data/test/nitro/server/tc_session.rb +0 -34
- data/test/nitro/tc_events.rb +0 -44
- data/test/nitro/tc_html.rb +0 -79
- data/test/nitro/tc_http.rb +0 -18
@@ -0,0 +1,105 @@
|
|
1
|
+
#--
|
2
|
+
# George Moschovitis <gm@navel.gr>
|
3
|
+
# (c) 2004-2005 Navel, all rights reserved.
|
4
|
+
# $Id$
|
5
|
+
#++
|
6
|
+
|
7
|
+
module N
|
8
|
+
|
9
|
+
require 'nitro/controller'
|
10
|
+
|
11
|
+
# The Dispatcher manages a set of controllers.
|
12
|
+
|
13
|
+
class Dispatcher
|
14
|
+
|
15
|
+
# The root directory.
|
16
|
+
|
17
|
+
attr_accessor :root
|
18
|
+
|
19
|
+
# The controllers map.
|
20
|
+
|
21
|
+
attr_accessor :controllers
|
22
|
+
|
23
|
+
# APIs map.
|
24
|
+
|
25
|
+
attr_accessor :apis
|
26
|
+
|
27
|
+
def initialize(controllers = nil, apis = nil)
|
28
|
+
@root = 'root'
|
29
|
+
@controllers = controllers || { :index => Controller }
|
30
|
+
@apis = apis
|
31
|
+
end
|
32
|
+
|
33
|
+
# Process the given hash and mount the
|
34
|
+
# defined controllers.
|
35
|
+
#
|
36
|
+
# [+controllers+]
|
37
|
+
# A hash representing the mapping of
|
38
|
+
# mount points to controllers.
|
39
|
+
#
|
40
|
+
# === Examples
|
41
|
+
#
|
42
|
+
# dispatcher.mount {
|
43
|
+
# :index => MainController # mounts /
|
44
|
+
# 'users' => UsersController # mounts /users
|
45
|
+
# }
|
46
|
+
|
47
|
+
def mount(controllers)
|
48
|
+
(@controllers ||= {}).update(controllers)
|
49
|
+
end
|
50
|
+
|
51
|
+
# Add a new api to the dispatcher
|
52
|
+
#
|
53
|
+
# [+api+]
|
54
|
+
# API symbol
|
55
|
+
# [+data+]
|
56
|
+
# Data for this API [content_type, ..]
|
57
|
+
|
58
|
+
def add_api(api, data)
|
59
|
+
(@apis ||= {})[api] = data
|
60
|
+
end
|
61
|
+
|
62
|
+
# Processes the path and dispatches to the corresponding
|
63
|
+
# controller/action pair.
|
64
|
+
# The base returned contains a trailing '/'.
|
65
|
+
|
66
|
+
def dispatch(path)
|
67
|
+
api = :xhtml
|
68
|
+
|
69
|
+
if @apis
|
70
|
+
@apis.each { |k, v| api = k if path.slice!(/#{k}\//) }
|
71
|
+
end
|
72
|
+
|
73
|
+
parts = path.split('/')
|
74
|
+
|
75
|
+
case parts.size
|
76
|
+
when 0
|
77
|
+
base = @root
|
78
|
+
controller_class = @controllers[:index]
|
79
|
+
action = 'index'
|
80
|
+
|
81
|
+
when 2
|
82
|
+
if controller_class = @controllers[parts[1]]
|
83
|
+
base = "#{@root}/#{parts[1]}"
|
84
|
+
action = 'index'
|
85
|
+
else
|
86
|
+
base = @root
|
87
|
+
controller_class = @controllers[:index]
|
88
|
+
action = parts[1]
|
89
|
+
end
|
90
|
+
|
91
|
+
when 3
|
92
|
+
base = "#{@root}/#{parts[1]}"
|
93
|
+
controller_class = @controllers[parts[1]]
|
94
|
+
action = parts[2]
|
95
|
+
end
|
96
|
+
|
97
|
+
content_type = @apis ? @apis[:api] : 'text/html'
|
98
|
+
|
99
|
+
return controller_class, "__#{api}__#{action}", base, content_type
|
100
|
+
end
|
101
|
+
alias_method :split_path, :dispatch
|
102
|
+
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
data/lib/nitro/filters.rb
CHANGED
@@ -1,17 +1,15 @@
|
|
1
|
-
|
2
|
-
#
|
3
|
-
#
|
1
|
+
#--
|
2
|
+
# George Moschovitis <gm@navel.gr>
|
4
3
|
# (c) 2004 Navel, all rights reserved.
|
5
|
-
# $Id: filters.rb
|
4
|
+
# $Id: filters.rb 215 2005-01-24 10:44:05Z gmosx $
|
5
|
+
#++
|
6
6
|
|
7
7
|
module N
|
8
8
|
|
9
|
-
# = Filtering
|
10
|
-
#
|
11
9
|
# Filtering functionality for renders/services. The design
|
12
10
|
# and implementation is HEAVILY influenced by Rails.
|
13
11
|
#
|
14
|
-
# Examples
|
12
|
+
# == Examples
|
15
13
|
#
|
16
14
|
# Filter as class:
|
17
15
|
#
|
@@ -22,10 +20,11 @@ module N
|
|
22
20
|
# before
|
23
21
|
# filter
|
24
22
|
# after
|
25
|
-
|
23
|
+
#--
|
26
24
|
# TODO:
|
27
25
|
# implement inheritable filters.
|
28
|
-
|
26
|
+
#++
|
27
|
+
|
29
28
|
module Filtering
|
30
29
|
|
31
30
|
# Ruby is sometimes VERY surprising, the following trick is needed
|
@@ -154,4 +153,4 @@ module Filtering
|
|
154
153
|
|
155
154
|
end
|
156
155
|
|
157
|
-
end
|
156
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# * George Moschovitis <gm@navel.gr>
|
2
|
+
# (c) 2004-2005 Navel, all rights reserved.
|
3
|
+
# $Id: l10n.rb 185 2004-12-10 13:29:09Z gmosx $
|
4
|
+
|
5
|
+
require 'nitro/filters'
|
6
|
+
|
7
|
+
module N
|
8
|
+
|
9
|
+
# Localization support.
|
10
|
+
#--
|
11
|
+
# TODO: use inflector to convert symbols to strings.
|
12
|
+
#++
|
13
|
+
|
14
|
+
class Localization
|
15
|
+
|
16
|
+
# This map gives the correct localization hash
|
17
|
+
# for the given locale.
|
18
|
+
|
19
|
+
attr_accessor :map
|
20
|
+
|
21
|
+
def initialize(map = {})
|
22
|
+
@map = map
|
23
|
+
end
|
24
|
+
|
25
|
+
# Return the localization hash for the given
|
26
|
+
# locale.
|
27
|
+
|
28
|
+
def get(locale = 'en')
|
29
|
+
locale || = 'en'
|
30
|
+
@map[locale]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# Localization filter
|
35
|
+
|
36
|
+
module LocalizationFilter
|
37
|
+
def localize
|
38
|
+
@lc = @context.conf.lc.get(@session[:LC])
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
data/lib/nitro/mail.rb
CHANGED
@@ -1,28 +1,25 @@
|
|
1
|
-
# code:
|
2
1
|
# * George Moschovitis <gm@navel.gr>
|
3
|
-
#
|
4
|
-
#
|
5
|
-
# $Id: mail.rb 164 2004-11-18 11:47:50Z gmosx $
|
2
|
+
# (c) 2004-2005 Navel, all rights reserved.
|
3
|
+
# $Id: mail.rb 248 2005-01-31 13:38:34Z gmosx $
|
6
4
|
|
7
|
-
require
|
5
|
+
require 'net/smtp'
|
8
6
|
|
9
7
|
module N
|
10
8
|
|
11
|
-
# = Mail
|
12
|
-
#
|
13
9
|
# A thin wrapper arround net/smtp
|
14
|
-
|
10
|
+
|
15
11
|
module Mail
|
16
|
-
|
12
|
+
|
13
|
+
mattr_accessor :smtp_server, 'localhost'
|
14
|
+
|
17
15
|
# Send an email
|
18
|
-
|
19
|
-
#
|
16
|
+
|
20
17
|
def self.send(from, to, body)
|
21
|
-
Net::SMTP.start(
|
18
|
+
Net::SMTP.start(N::Mail.smtp_server, 25) do |smtp|
|
22
19
|
smtp.send_message(body, from, to)
|
23
|
-
|
20
|
+
end
|
24
21
|
end
|
25
22
|
|
26
23
|
end
|
27
24
|
|
28
|
-
end
|
25
|
+
end
|
data/lib/nitro/render.rb
ADDED
@@ -0,0 +1,275 @@
|
|
1
|
+
# * George Moschovitis <gm@navel.gr>
|
2
|
+
# (c) 2004-2005 Navel, all rights reserved.
|
3
|
+
# $Id$
|
4
|
+
|
5
|
+
require 'glue/attribute'
|
6
|
+
require 'glue/misc'
|
7
|
+
require 'glue/object'
|
8
|
+
|
9
|
+
require 'nitro/shaders'
|
10
|
+
require 'nitro/buffering'
|
11
|
+
|
12
|
+
module N
|
13
|
+
|
14
|
+
# Raise this exception to stop rendering.
|
15
|
+
|
16
|
+
class RenderExit < Exception; end
|
17
|
+
|
18
|
+
# Rendering utility methods
|
19
|
+
|
20
|
+
module Rendering
|
21
|
+
|
22
|
+
# The default template name (no extension).
|
23
|
+
|
24
|
+
mattr_accessor :default_template, 'index'
|
25
|
+
|
26
|
+
# The shader used for transforming templates.
|
27
|
+
# The default shader is very simple, here is a
|
28
|
+
# typical example of a production shader pipeline:
|
29
|
+
#
|
30
|
+
# <tt>
|
31
|
+
# Rendering.shader =
|
32
|
+
# XSLTShader.new("xsl/style.xsl",
|
33
|
+
# RubyShader.new(
|
34
|
+
# CompressShader.new
|
35
|
+
# )
|
36
|
+
# )
|
37
|
+
# </tt>
|
38
|
+
|
39
|
+
mattr_accessor :shader; @@shader = RubyShader.new
|
40
|
+
|
41
|
+
# If true, reloads all controllers. Useful in
|
42
|
+
# development.
|
43
|
+
|
44
|
+
mattr_accessor :reload, :partial
|
45
|
+
|
46
|
+
# Given the action try find the matching template.
|
47
|
+
# Can search for xhtml or xml templates.
|
48
|
+
# Returns nil if no template file is found.
|
49
|
+
|
50
|
+
def self.template_for_action(base, action, ext = :xhtml)
|
51
|
+
|
52
|
+
# attempt to find a template of the form
|
53
|
+
# base/action.xhtml
|
54
|
+
|
55
|
+
path = "#{base}/#{action}.#{ext}".squeeze('/')
|
56
|
+
|
57
|
+
unless File.exist?(path)
|
58
|
+
|
59
|
+
# attempt to find a template of the form
|
60
|
+
# base/action/index.xhtml
|
61
|
+
|
62
|
+
path = "#{base}/#{action}/#{Rendering.default_template}.#{ext}".squeeze('/')
|
63
|
+
|
64
|
+
unless File.exist?(path)
|
65
|
+
# No template found!
|
66
|
+
path = nil
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
return path
|
71
|
+
end
|
72
|
+
|
73
|
+
# Transform a template to ruby rendering code.
|
74
|
+
|
75
|
+
def self.transform_template(path, shader)
|
76
|
+
Logger.debug "Transforming '#{path}'" if $DBG
|
77
|
+
|
78
|
+
text = File.read(path)
|
79
|
+
hash, text = shader.process(path, text)
|
80
|
+
|
81
|
+
return text
|
82
|
+
end
|
83
|
+
|
84
|
+
# Compile a controller action.
|
85
|
+
|
86
|
+
def self.compile_action(klass, action, base)
|
87
|
+
dummy, api, action = action.to_s.split('__')
|
88
|
+
|
89
|
+
# This is not a controller action.
|
90
|
+
|
91
|
+
return false unless action
|
92
|
+
|
93
|
+
Logger.debug "Compiling action '#{base}/#{action}'" if $DBG
|
94
|
+
|
95
|
+
valid = false
|
96
|
+
|
97
|
+
code = %{
|
98
|
+
def __#{api}__#{action}
|
99
|
+
}
|
100
|
+
|
101
|
+
# call 'before' filter chain.
|
102
|
+
|
103
|
+
if klass.respond_to?(:before_filters)
|
104
|
+
code << %{
|
105
|
+
#{klass.gen_filters_call_code(klass.before_filters)}
|
106
|
+
}
|
107
|
+
end
|
108
|
+
|
109
|
+
# call the action
|
110
|
+
|
111
|
+
if klass.instance_methods.include?(action)
|
112
|
+
valid = true
|
113
|
+
code << %{
|
114
|
+
#{action}();
|
115
|
+
}
|
116
|
+
end
|
117
|
+
|
118
|
+
# call the programmatically generated template if exists.
|
119
|
+
|
120
|
+
if klass.instance_methods.include?("#{action}__#{api}")
|
121
|
+
valid = true
|
122
|
+
code << %{
|
123
|
+
return unless #{action}__#{api}();
|
124
|
+
}
|
125
|
+
end
|
126
|
+
|
127
|
+
# call the template if exists.
|
128
|
+
|
129
|
+
if template = template_for_action(base, action)
|
130
|
+
valid = true
|
131
|
+
code << %{
|
132
|
+
return unless __#{api}__#{action}__template();
|
133
|
+
}
|
134
|
+
end
|
135
|
+
|
136
|
+
# raise "Invalid action '#{action}' for '#{klass}'!" unless valid
|
137
|
+
return false unless valid
|
138
|
+
|
139
|
+
# call 'after' filter chain.
|
140
|
+
|
141
|
+
if klass.respond_to?(:after_filters)
|
142
|
+
code << %{
|
143
|
+
#{klass.gen_filters_call_code(klass.after_filters)}
|
144
|
+
}
|
145
|
+
end
|
146
|
+
|
147
|
+
code << %{
|
148
|
+
redirect_referer if @out.empty?
|
149
|
+
end
|
150
|
+
}
|
151
|
+
|
152
|
+
if template
|
153
|
+
code << %{
|
154
|
+
def __#{api}__#{action}__template
|
155
|
+
#{transform_template(template, Rendering.shader)}
|
156
|
+
end
|
157
|
+
}
|
158
|
+
end
|
159
|
+
|
160
|
+
klass.class_eval(code)
|
161
|
+
|
162
|
+
return true
|
163
|
+
end
|
164
|
+
|
165
|
+
end
|
166
|
+
|
167
|
+
# The rendering mixin.
|
168
|
+
|
169
|
+
module Render
|
170
|
+
|
171
|
+
# The outbut buffer. The output of a script/action is accumulated
|
172
|
+
# in this buffer.
|
173
|
+
|
174
|
+
attr_accessor :out
|
175
|
+
|
176
|
+
# The context.
|
177
|
+
|
178
|
+
attr_accessor :context
|
179
|
+
alias_method :ctx, :context
|
180
|
+
alias_method :ctx=, :context=
|
181
|
+
alias_method :request, :context
|
182
|
+
|
183
|
+
# An array holding the rendering errors for this
|
184
|
+
# request.
|
185
|
+
|
186
|
+
attr_accessor :rendering_errors
|
187
|
+
|
188
|
+
# Initialize the render.
|
189
|
+
#
|
190
|
+
# [+context+]
|
191
|
+
# A parent render/controller acts as the context.
|
192
|
+
|
193
|
+
def initialize(context, base)
|
194
|
+
@context = context
|
195
|
+
@out = context.out
|
196
|
+
@base = base
|
197
|
+
end
|
198
|
+
|
199
|
+
# Renders the action denoted by path. The path
|
200
|
+
# is resolved by the dispatcher to get the correct
|
201
|
+
# controller.
|
202
|
+
|
203
|
+
def render(path)
|
204
|
+
Logger.debug "Rendering '#{path}'." if $DBG
|
205
|
+
|
206
|
+
klass, action, base, ctype = @context.dispatcher.dispatch(path)
|
207
|
+
|
208
|
+
if :full == Rendering.reload
|
209
|
+
def_file = klass::DEF_FILE
|
210
|
+
Controller.remove_subclasses
|
211
|
+
load(def_file)
|
212
|
+
end
|
213
|
+
|
214
|
+
@context.content_type = ctype
|
215
|
+
|
216
|
+
raise 'No controller for action' unless klass
|
217
|
+
|
218
|
+
if self.class == klass
|
219
|
+
self.send(action)
|
220
|
+
else
|
221
|
+
klass.new(self, base).send(action)
|
222
|
+
end
|
223
|
+
|
224
|
+
rescue RenderExit => e
|
225
|
+
|
226
|
+
# Just stop rendering.
|
227
|
+
# For example called by redirects.
|
228
|
+
|
229
|
+
rescue Exception, StandardError => e
|
230
|
+
log_error "Error while handling '#{path}'."
|
231
|
+
log_error pp_exception(e)
|
232
|
+
|
233
|
+
# More fault tolerant, only flags the erroneous box with
|
234
|
+
# error not the full page.
|
235
|
+
|
236
|
+
@out << '(error)'
|
237
|
+
end
|
238
|
+
|
239
|
+
# Send a redirect response.
|
240
|
+
|
241
|
+
def redirect(url, status = 303)
|
242
|
+
@context.status = status
|
243
|
+
@context.out = "<html><a href=\"#{url.to_s}\">#{url.to_s}</a>.</html>\n"
|
244
|
+
@context.response_headers['location'] = url.to_s
|
245
|
+
|
246
|
+
raise RenderExit
|
247
|
+
end
|
248
|
+
|
249
|
+
# Redirect to the referer of this method.
|
250
|
+
|
251
|
+
def redirect_referer(postfix = nil, status = 303)
|
252
|
+
redirect("#{@context.referer}#{postfix}", status)
|
253
|
+
end
|
254
|
+
|
255
|
+
# Log a rendering error.
|
256
|
+
|
257
|
+
def log_error(str)
|
258
|
+
@rendering_errors ||= []
|
259
|
+
@rendering_errors << str
|
260
|
+
|
261
|
+
# gmosx: Hmm perhaps this should not be logged
|
262
|
+
# to avoid DOS attacks.
|
263
|
+
|
264
|
+
Logger.error str
|
265
|
+
end
|
266
|
+
|
267
|
+
# Convenience method to lookup the session.
|
268
|
+
|
269
|
+
def session
|
270
|
+
@context.session
|
271
|
+
end
|
272
|
+
|
273
|
+
end
|
274
|
+
|
275
|
+
end
|