nitro 0.8.0 → 0.9.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (198) hide show
  1. data/AUTHORS +3 -4
  2. data/ChangeLog +418 -0
  3. data/LICENSE +1 -1
  4. data/README +157 -89
  5. data/RELEASES +50 -0
  6. data/Rakefile +5 -7
  7. data/benchmark/nitro/bench.rb +5 -0
  8. data/benchmark/nitro/simple-webrick-n-200.txt +44 -0
  9. data/benchmark/nitro/static-webrick-n-200.txt +43 -0
  10. data/benchmark/nitro/tiny-lhttpd-n-200-c-5.txt +43 -0
  11. data/benchmark/nitro/tiny-webrick-n-200-c-5.txt +44 -0
  12. data/benchmark/nitro/tiny-webrick-n-200.txt +44 -0
  13. data/benchmark/nitro/tiny2-webrick-n-200.txt +44 -0
  14. data/{lib/nitro/server/cluster.rb → bin/cluster} +26 -30
  15. data/bin/proto/README +2 -2
  16. data/bin/proto/{apache.conf → conf/apache.conf} +0 -0
  17. data/bin/proto/conf/app.conf.rb +22 -0
  18. data/bin/proto/conf/lhttpd.conf +236 -0
  19. data/bin/proto/ctl +4 -0
  20. data/bin/proto/lib/README +5 -0
  21. data/bin/proto/log/README +3 -0
  22. data/bin/proto/root/fcgi.rb +6 -0
  23. data/bin/proto/root/index.xhtml +65 -7
  24. data/bin/proto/root/m/nitro.png +0 -0
  25. data/examples/blog/README +7 -5
  26. data/examples/blog/{apache.conf → conf/apache.conf} +0 -0
  27. data/examples/blog/conf/app.conf.rb +56 -0
  28. data/examples/blog/conf/lhttpd.conf +236 -0
  29. data/examples/blog/ctl +4 -0
  30. data/examples/blog/lib/blog.rb +11 -136
  31. data/examples/blog/lib/blog/controller.rb +99 -0
  32. data/examples/blog/lib/blog/model.rb +39 -0
  33. data/examples/blog/log/README +3 -0
  34. data/examples/blog/root/comments.xhtml +2 -2
  35. data/examples/blog/root/fcgi.rb +6 -0
  36. data/examples/blog/root/index.xhtml +4 -5
  37. data/examples/blog/root/login.xhtml +2 -2
  38. data/examples/blog/root/style.xsl +9 -9
  39. data/examples/blog/root/view_entry.xhtml +2 -2
  40. data/examples/flash/conf/app.conf.rb +23 -0
  41. data/examples/flash/ctl +4 -0
  42. data/examples/flash/log/README +3 -0
  43. data/examples/flash/root/index.xhtml +0 -9
  44. data/examples/flash/root/show_inline_text.xhtml +10 -5
  45. data/examples/no_xsl_blog/README +12 -0
  46. data/examples/no_xsl_blog/conf/apache.conf +0 -0
  47. data/examples/no_xsl_blog/conf/app.conf.rb +57 -0
  48. data/examples/no_xsl_blog/conf/lhttpd.conf +236 -0
  49. data/examples/no_xsl_blog/ctl +4 -0
  50. data/examples/no_xsl_blog/lib/blog.rb +20 -0
  51. data/examples/no_xsl_blog/lib/blog/controller.rb +102 -0
  52. data/examples/no_xsl_blog/lib/blog/model.rb +39 -0
  53. data/examples/no_xsl_blog/lib/blog/template.rb +134 -0
  54. data/examples/no_xsl_blog/log/README +3 -0
  55. data/examples/no_xsl_blog/root/comments.xhtml +41 -0
  56. data/examples/no_xsl_blog/root/entry_form.xhtml +22 -0
  57. data/examples/no_xsl_blog/root/fcgi.rb +6 -0
  58. data/examples/no_xsl_blog/root/index.xhtml +39 -0
  59. data/examples/no_xsl_blog/root/login.xhtml +21 -0
  60. data/examples/no_xsl_blog/root/m/bubbles.gif +0 -0
  61. data/examples/no_xsl_blog/root/m/comments_curve.gif +0 -0
  62. data/examples/no_xsl_blog/root/m/down.gif +0 -0
  63. data/examples/no_xsl_blog/root/m/footer_bg.gif +0 -0
  64. data/examples/no_xsl_blog/root/m/garrow.gif +0 -0
  65. data/examples/no_xsl_blog/root/m/gbull.gif +0 -0
  66. data/examples/no_xsl_blog/root/m/grbull.gif +0 -0
  67. data/examples/no_xsl_blog/root/m/h1_bg.gif +0 -0
  68. data/examples/no_xsl_blog/root/m/header_bg.gif +0 -0
  69. data/examples/no_xsl_blog/root/m/nitro.gif +0 -0
  70. data/examples/no_xsl_blog/root/m/obull.gif +0 -0
  71. data/examples/no_xsl_blog/root/m/page_bg.gif +0 -0
  72. data/examples/no_xsl_blog/root/m/rss.gif +0 -0
  73. data/examples/no_xsl_blog/root/m/side_title_bg.gif +0 -0
  74. data/examples/no_xsl_blog/root/m/sidebar_bg.gif +0 -0
  75. data/examples/no_xsl_blog/root/recent_posts.xhtml +14 -0
  76. data/examples/no_xsl_blog/root/style.css +301 -0
  77. data/examples/no_xsl_blog/root/view_entry.xhtml +25 -0
  78. data/examples/no_xsl_blog/root/view_entry.xml +12 -0
  79. data/examples/og/run.rb +2 -2
  80. data/examples/tiny/README +2 -2
  81. data/examples/tiny/conf/apache.conf +5 -0
  82. data/examples/tiny/conf/app.conf.rb +21 -0
  83. data/examples/tiny/conf/lhttpd.conf +236 -0
  84. data/examples/tiny/ctl +4 -0
  85. data/examples/tiny/log/README +3 -0
  86. data/examples/tiny/root/fcgi.rb +6 -0
  87. data/examples/tiny/root/index.xhtml +7 -4
  88. data/examples/tiny/root/nitro.png +0 -0
  89. data/lib/glue.rb +13 -9
  90. data/lib/glue/array.rb +1 -1
  91. data/lib/glue/cache.rb +1 -1
  92. data/lib/glue/flexob.rb +12 -0
  93. data/lib/glue/hash.rb +1 -1
  94. data/lib/glue/inflector.rb +2 -2
  95. data/lib/glue/logger.rb +4 -8
  96. data/lib/glue/misc.rb +14 -0
  97. data/lib/glue/number.rb +1 -1
  98. data/lib/glue/object.rb +26 -0
  99. data/lib/glue/pool.rb +1 -1
  100. data/lib/glue/property.rb +84 -91
  101. data/lib/glue/string.rb +1 -1
  102. data/lib/glue/time.rb +1 -1
  103. data/lib/glue/validation.rb +1 -1
  104. data/lib/nitro.rb +18 -6
  105. data/lib/nitro/adaptors/cgi.rb +291 -0
  106. data/lib/nitro/adaptors/fastcgi.rb +42 -0
  107. data/lib/nitro/adaptors/runner.rb +123 -0
  108. data/lib/nitro/adaptors/webrick.rb +110 -0
  109. data/lib/nitro/buffering.rb +43 -0
  110. data/lib/nitro/builders/form.rb +1 -1
  111. data/lib/nitro/builders/rss.rb +1 -1
  112. data/{bin → lib/nitro}/cluster.rb +26 -30
  113. data/lib/nitro/context.rb +82 -0
  114. data/lib/nitro/controller.rb +50 -0
  115. data/lib/nitro/cookie.rb +46 -0
  116. data/lib/nitro/dispatcher.rb +105 -0
  117. data/lib/nitro/filters.rb +9 -10
  118. data/lib/nitro/localization.rb +42 -0
  119. data/lib/nitro/mail.rb +11 -14
  120. data/lib/nitro/render.rb +275 -0
  121. data/lib/nitro/request.rb +128 -0
  122. data/lib/nitro/response.rb +38 -0
  123. data/lib/nitro/scaffold.rb +11 -11
  124. data/lib/nitro/session.rb +84 -0
  125. data/lib/nitro/{server/shaders.rb → shaders.rb} +56 -36
  126. data/lib/nitro/ui/pager.rb +23 -26
  127. data/lib/nitro/{sitemap.rb → ui/sitemap.rb} +4 -12
  128. data/lib/nitro/uri.rb +1 -1
  129. data/lib/nitro/version.rb +10 -8
  130. data/lib/og.rb +66 -65
  131. data/lib/og/backend.rb +1 -1
  132. data/lib/og/backends/mysql.rb +48 -52
  133. data/lib/og/backends/psql.rb +34 -37
  134. data/lib/og/connection.rb +15 -15
  135. data/lib/og/enchant.rb +16 -9
  136. data/lib/og/meta.rb +127 -54
  137. data/lib/og/mock.rb +18 -18
  138. data/lib/og/version.rb +6 -4
  139. data/lib/parts/content.rb +4 -8
  140. data/test/glue/tc_logger.rb +3 -0
  141. data/test/glue/tc_property.rb +19 -3
  142. data/test/nitro/adaptors/tc_cgi.rb +63 -0
  143. data/test/nitro/adaptors/tc_webrick.rb +15 -0
  144. data/test/nitro/builders/tc_xml.rb +2 -2
  145. data/test/nitro/tc_context.rb +13 -0
  146. data/test/nitro/tc_controller.rb +47 -0
  147. data/test/nitro/tc_dispatcher.rb +64 -0
  148. data/test/nitro/tc_session.rb +20 -0
  149. data/test/nitro/{tc_sitemap.rb → ui/tc_sitemap.rb} +1 -1
  150. data/test/root/blog/list.xhtml +6 -0
  151. data/test/tc_og.rb +41 -4
  152. metadata +115 -59
  153. data/bin/proto/app.rb +0 -20
  154. data/bin/proto/config.rb +0 -77
  155. data/examples/blog/app.rb +0 -21
  156. data/examples/blog/config.rb +0 -95
  157. data/examples/blog/env.rb +0 -22
  158. data/examples/flash/README +0 -34
  159. data/examples/flash/app.rb +0 -20
  160. data/examples/flash/config.rb +0 -38
  161. data/examples/flash/lib/flash.rb +0 -40
  162. data/examples/flash/tmp.swf +0 -0
  163. data/examples/tiny/app.rb +0 -19
  164. data/examples/tiny/config.rb +0 -29
  165. data/examples/tiny/root/nitro-small.png +0 -0
  166. data/lib/nitro/application.rb +0 -217
  167. data/lib/nitro/config.rb +0 -128
  168. data/lib/nitro/events.rb +0 -122
  169. data/lib/nitro/html.rb +0 -151
  170. data/lib/nitro/http.rb +0 -102
  171. data/lib/nitro/l10n.rb +0 -30
  172. data/lib/nitro/server.rb +0 -59
  173. data/lib/nitro/server/appserver.rb +0 -67
  174. data/lib/nitro/server/cookie.rb +0 -87
  175. data/lib/nitro/server/dispatcher.rb +0 -62
  176. data/lib/nitro/server/filters.rb +0 -75
  177. data/lib/nitro/server/filters/autologin.rb +0 -51
  178. data/lib/nitro/server/fragment.rb +0 -70
  179. data/lib/nitro/server/handlers.rb +0 -127
  180. data/lib/nitro/server/render.rb +0 -426
  181. data/lib/nitro/server/request.rb +0 -658
  182. data/lib/nitro/server/requestpart.rb +0 -54
  183. data/lib/nitro/server/script.rb +0 -387
  184. data/lib/nitro/server/server.rb +0 -57
  185. data/lib/nitro/server/session.rb +0 -220
  186. data/lib/nitro/server/user.rb +0 -46
  187. data/lib/nitro/server/webrick.rb +0 -180
  188. data/lib/nitro/service.rb +0 -26
  189. data/lib/xsl/ui.xsl +0 -51
  190. data/lib/xsl/xforms.xsl +0 -28
  191. data/test/nitro/server/tc_cookie.rb +0 -34
  192. data/test/nitro/server/tc_filters.rb +0 -38
  193. data/test/nitro/server/tc_request.rb +0 -70
  194. data/test/nitro/server/tc_requestpart.rb +0 -28
  195. data/test/nitro/server/tc_session.rb +0 -34
  196. data/test/nitro/tc_events.rb +0 -44
  197. data/test/nitro/tc_html.rb +0 -79
  198. 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
@@ -1,17 +1,15 @@
1
- # code:
2
- # * George Moschovitis <gm@navel.gr>
3
- #
1
+ #--
2
+ # George Moschovitis <gm@navel.gr>
4
3
  # (c) 2004 Navel, all rights reserved.
5
- # $Id: filters.rb 184 2004-12-07 14:42:22Z gmosx $
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 # module
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
@@ -1,28 +1,25 @@
1
- # code:
2
1
  # * George Moschovitis <gm@navel.gr>
3
- #
4
- # (c) 2004 Navel, all rights reserved.
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 "net/smtp"
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($smtp_server, 25) { |smtp|
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 # module
25
+ end
@@ -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