aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack
diff options
context:
space:
mode:
Diffstat (limited to 'actionpack')
-rw-r--r--actionpack/lib/action_view/flows.rb9
-rw-r--r--actionpack/lib/action_view/helpers/capture_helper.rb8
-rw-r--r--actionpack/test/fixtures/layouts/streaming.erb4
-rw-r--r--actionpack/test/fixtures/test/nested_streaming.erb3
-rw-r--r--actionpack/test/fixtures/test/streaming.erb3
-rw-r--r--actionpack/test/fixtures/test/streaming_buster.erb3
-rw-r--r--actionpack/test/template/capture_helper_test.rb11
-rw-r--r--actionpack/test/template/streaming_render_test.rb12
8 files changed, 43 insertions, 10 deletions
diff --git a/actionpack/lib/action_view/flows.rb b/actionpack/lib/action_view/flows.rb
index b5e2c5d37d..995a0b51e4 100644
--- a/actionpack/lib/action_view/flows.rb
+++ b/actionpack/lib/action_view/flows.rb
@@ -19,6 +19,10 @@ module ActionView
def append(key, value)
@content[key] << value
end
+
+ def append!(key, value)
+ @content[key] << value
+ end
end
class StreamingFlow < OutputFlow
@@ -58,6 +62,11 @@ module ActionView
# by provides and resumes back to the fiber if it is
# the key it is waiting for.
def set(key, value)
+ @content[key] = (ActiveSupport::SafeBuffer.new << value)
+ end
+
+ # Append but also resume the fiber if it provided the right key.
+ def append!(key, value)
super
@fiber.resume if @waiting_for == key
end
diff --git a/actionpack/lib/action_view/helpers/capture_helper.rb b/actionpack/lib/action_view/helpers/capture_helper.rb
index 148d814ac7..0139714240 100644
--- a/actionpack/lib/action_view/helpers/capture_helper.rb
+++ b/actionpack/lib/action_view/helpers/capture_helper.rb
@@ -142,12 +142,12 @@ module ActionView
# The same as +content_for+ but when used with streaming flushes
# straight back to the layout. In other words, if you want to
# concatenate several times to the same buffer when rendering a given
- # template, you should use +content_for+, if not, use +provide+ as it
- # has better streaming support.
+ # template, you should use +content_for+, if not, use +provide+ to tell
+ # the layout to stop looking for more contents.
def provide(name, content = nil, &block)
content = capture(&block) if block_given?
- @_view_flow.set(name, content) if content
- content
+ result = @_view_flow.append!(name, content) if content
+ result unless content
end
# content_for? simply checks whether any content has been captured yet using content_for
diff --git a/actionpack/test/fixtures/layouts/streaming.erb b/actionpack/test/fixtures/layouts/streaming.erb
new file mode 100644
index 0000000000..d3f896a6ca
--- /dev/null
+++ b/actionpack/test/fixtures/layouts/streaming.erb
@@ -0,0 +1,4 @@
+<%= yield :header -%>
+<%= yield -%>
+<%= yield :footer -%>
+<%= yield(:unknown).presence || "." -%> \ No newline at end of file
diff --git a/actionpack/test/fixtures/test/nested_streaming.erb b/actionpack/test/fixtures/test/nested_streaming.erb
new file mode 100644
index 0000000000..55525e0c92
--- /dev/null
+++ b/actionpack/test/fixtures/test/nested_streaming.erb
@@ -0,0 +1,3 @@
+<%- content_for :header do -%>?<%- end -%>
+<%= render :template => "test/streaming" %>
+? \ No newline at end of file
diff --git a/actionpack/test/fixtures/test/streaming.erb b/actionpack/test/fixtures/test/streaming.erb
new file mode 100644
index 0000000000..fb9b8b1ade
--- /dev/null
+++ b/actionpack/test/fixtures/test/streaming.erb
@@ -0,0 +1,3 @@
+<%- provide :header do -%>Yes, <%- end -%>
+this works
+<%- content_for :footer, " like a charm" -%>
diff --git a/actionpack/test/fixtures/test/streaming_buster.erb b/actionpack/test/fixtures/test/streaming_buster.erb
new file mode 100644
index 0000000000..4221d56dcc
--- /dev/null
+++ b/actionpack/test/fixtures/test/streaming_buster.erb
@@ -0,0 +1,3 @@
+<%= yield :foo -%>
+This won't look
+<% provide :unknown, " good." -%>
diff --git a/actionpack/test/template/capture_helper_test.rb b/actionpack/test/template/capture_helper_test.rb
index c2f0825375..a9a36e6e6b 100644
--- a/actionpack/test/template/capture_helper_test.rb
+++ b/actionpack/test/template/capture_helper_test.rb
@@ -47,13 +47,16 @@ class CaptureHelperTest < ActionView::TestCase
def test_provide
assert !content_for?(:title)
- provide :title, "title"
+ provide :title, "hi"
assert content_for?(:title)
- assert_equal "title", @_view_flow.get(:title)
+ assert_equal "hi", @_view_flow.get(:title)
provide :title, "<p>title</p>"
- assert_equal "&lt;p&gt;title&lt;/p&gt;", @_view_flow.get(:title)
+ assert_equal "hi&lt;p&gt;title&lt;/p&gt;", @_view_flow.get(:title)
+
+ @_view_flow = ActionView::OutputFlow.new
+ provide :title, "hi"
provide :title, "<p>title</p>".html_safe
- assert_equal "<p>title</p>", @_view_flow.get(:title)
+ assert_equal "hi<p>title</p>", @_view_flow.get(:title)
end
def test_with_output_buffer_swaps_the_output_buffer_given_no_argument
diff --git a/actionpack/test/template/streaming_render_test.rb b/actionpack/test/template/streaming_render_test.rb
index 754ede9701..4d69081570 100644
--- a/actionpack/test/template/streaming_render_test.rb
+++ b/actionpack/test/template/streaming_render_test.rb
@@ -88,10 +88,18 @@ class FiberedTest < ActiveSupport::TestCase
end
def test_render_with_streaming_multiple_yields_provide_and_content_for
- assert_equal "Yes, \nthis works\n like a charm.", buffered_render(:template => "test/streaming", :layout => "layouts/streaming")
+ assert_equal "Yes, \nthis works\n like a charm.",
+ buffered_render(:template => "test/streaming", :layout => "layouts/streaming")
end
def test_render_with_streaming_with_fake_yields_and_streaming_buster
- assert_equal "This won't look\n good.", buffered_render(:template => "test/streaming_buster", :layout => "layouts/streaming")
+ assert_equal "This won't look\n good.",
+ buffered_render(:template => "test/streaming_buster", :layout => "layouts/streaming")
end
+
+ def test_render_with_nested_streaming_multiple_yields_provide_and_content_for
+ assert_equal "?Yes, \n\nthis works\n\n? like a charm.",
+ buffered_render(:template => "test/nested_streaming", :layout => "layouts/streaming")
+ end
+
end if defined?(Fiber) \ No newline at end of file