diff options
-rw-r--r-- | actionpack/lib/action_view/base.rb | 6 | ||||
-rw-r--r-- | actionpack/lib/action_view/renderer/streaming_template_renderer.rb | 11 | ||||
-rw-r--r-- | actionpack/test/controller/new_base/render_streaming_test.rb | 24 |
3 files changed, 35 insertions, 6 deletions
diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb index 9e8a3c51a3..87501d5b88 100644 --- a/actionpack/lib/action_view/base.rb +++ b/actionpack/lib/action_view/base.rb @@ -137,6 +137,12 @@ module ActionView #:nodoc: cattr_accessor :field_error_proc @@field_error_proc = Proc.new{ |html_tag, instance| "<div class=\"field_with_errors\">#{html_tag}</div>".html_safe } + # How to complete the streaming when an exception occurs. + # This is our best guess: first try to close the attribute, then the tag. + # Currently this is private API and may be changed at *any* time. + cattr_accessor :streaming_completion_on_exception + @@streaming_completion_on_exception = %("><script type="text/javascript">window.location = "/500.html"</script></html>) + class_attribute :helpers class_attribute :_routes diff --git a/actionpack/lib/action_view/renderer/streaming_template_renderer.rb b/actionpack/lib/action_view/renderer/streaming_template_renderer.rb index 52f0e9f5bd..03aab444f8 100644 --- a/actionpack/lib/action_view/renderer/streaming_template_renderer.rb +++ b/actionpack/lib/action_view/renderer/streaming_template_renderer.rb @@ -46,11 +46,8 @@ module ActionView # # == TODO # - # * Add streaming support in the controllers with no-cache settings - # * What should happen when an error happens? # * Support streaming from child templates, partials and so on. - # * Support on sprockets async JS load? - # + # * Integrate exceptions with exceptron class StreamingTemplateRenderer < TemplateRenderer #:nodoc: # A valid Rack::Body (i.e. it responds to each). # It is initialized with a block that, when called, starts @@ -61,7 +58,11 @@ module ActionView end def each(&block) - @start.call(block) + begin + @start.call(block) + rescue + block.call ActionView::Base.streaming_completion_on_exception + end self end end diff --git a/actionpack/test/controller/new_base/render_streaming_test.rb b/actionpack/test/controller/new_base/render_streaming_test.rb index ffc4b331ec..b8df5ec4e8 100644 --- a/actionpack/test/controller/new_base/render_streaming_test.rb +++ b/actionpack/test/controller/new_base/render_streaming_test.rb @@ -4,7 +4,9 @@ module RenderStreaming class BasicController < ActionController::Base self.view_paths = [ActionView::FixtureResolver.new( "render_streaming/basic/hello_world.html.erb" => "Hello world", - "layouts/application.html.erb" => "<%= yield %>, I'm here!" + "render_streaming/basic/boom.html.erb" => "<%= nil.invalid! %>", + "layouts/application.html.erb" => "<%= yield %>, I'm here!", + "layouts/boom.html.erb" => "<body class=\"<%= nil.invalid! %>\"<%= yield %></body>" )] layout "application" @@ -13,6 +15,14 @@ module RenderStreaming def hello_world end + def layout_exception + render :action => "hello_world", :stream => true, :layout => "boom" + end + + def template_exception + render :action => "boom", :stream => true + end + def skip render :action => "hello_world", :stream => false end @@ -61,6 +71,18 @@ module RenderStreaming assert_body "Hello world, I'm here!" end + test "rendering with layout exception" do + get "/render_streaming/basic/layout_exception" + assert_body "d\r\n<body class=\"\r\n4e\r\n\"><script type=\"text/javascript\">window.location = \"/500.html\"</script></html>\r\n0\r\n\r\n" + assert_streaming! + end + + test "rendering with template exception" do + get "/render_streaming/basic/template_exception" + assert_body "4e\r\n\"><script type=\"text/javascript\">window.location = \"/500.html\"</script></html>\r\n0\r\n\r\n" + assert_streaming! + end + def assert_streaming!(cache="no-cache") assert_status 200 assert_equal nil, headers["Content-Length"] |