nitro 0.8.0 → 0.9.3
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/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
|