diff --git a/actionpack/lib/action_view/helpers/capture_helper.rb b/actionpack/lib/action_view/helpers/capture_helper.rb index 0a0d31dded8c03805226e7efc780b10098be4e39..17bbfe2efd9f00857c55c58e5bcd92b15cd7fc61 100644 --- a/actionpack/lib/action_view/helpers/capture_helper.rb +++ b/actionpack/lib/action_view/helpers/capture_helper.rb @@ -81,8 +81,8 @@ def capture(*args) # <%# This is the layout %> # # - # My Website - # <%= yield :script %> + # My Website + # <%= yield :script %> # # # <%= yield %> @@ -110,7 +110,7 @@ def capture(*args) # That will place +script+ tags for your default set of JavaScript files on the page; # this technique is useful if you'll only be using these scripts in a few views. # - # Note that content_for concatenates the blocks it is given for a particular + # Note that content_for concatenates (default) the blocks it is given for a particular # identifier in order. For example: # # <% content_for :navigation do %> @@ -127,16 +127,37 @@ def capture(*args) # # # + # If the flush parameter is true content_for replaces the blocks it is given. For example: + # + # <% content_for :navigation do %> + #
  • <%= link_to 'Home', :action => 'index' %>
  • + # <% end %> + # + # <%# Add some other content, or use a different template: %> + # + # <% content_for :navigation, true do %> + #
  • <%= link_to 'Login', :action => 'login' %>
  • + # <% end %> + # + # Then, in another template or layout, this code would render only the last link: + # + # + # # Lastly, simple content can be passed as a parameter: # # <% content_for :script, javascript_include_tag(:defaults) %> # # WARNING: content_for is ignored in caches. So you shouldn't use it # for elements that will be fragment cached. - def content_for(name, content = nil, &block) + def content_for(name, content = nil, flush = false, &block) if content || block_given? - content = capture(&block) if block_given? - @view_flow.append(name, content) if content + if block_given? + flush = content if content + content = capture(&block) + end + if content + flush ? @view_flow.set(name, content) : @view_flow.append(name, content) + end nil else @view_flow.get(name) @@ -164,8 +185,8 @@ def provide(name, content = nil, &block) # <%# This is the layout %> # # - # My Website - # <%= yield :script %> + # My Website + # <%= yield :script %> # # # <%= yield %> diff --git a/actionpack/test/template/capture_helper_test.rb b/actionpack/test/template/capture_helper_test.rb index a37e3a8d6abbf15119a07fb3d0b0d41ca80daff1..17469f8c3e5f1c052876f6fab6c62a1e9477fb70 100644 --- a/actionpack/test/template/capture_helper_test.rb +++ b/actionpack/test/template/capture_helper_test.rb @@ -53,6 +53,13 @@ def test_content_for_with_multiple_calls assert_equal 'foobar', content_for(:title) end + def test_content_for_with_multiple_calls_and_flush + assert ! content_for?(:title) + content_for :title, 'foo' + content_for :title, 'bar', true + assert_equal 'bar', content_for(:title) + end + def test_content_for_with_block assert ! content_for?(:title) content_for :title do @@ -63,6 +70,39 @@ def test_content_for_with_block assert_equal 'foobar', content_for(:title) end + def test_content_for_with_block_and_multiple_calls_with_flush + assert ! content_for?(:title) + content_for :title do + 'foo' + end + content_for :title, true do + 'bar' + end + assert_equal 'bar', content_for(:title) + end + + def test_content_for_with_block_and_multiple_calls_with_flush_nil_content + assert ! content_for?(:title) + content_for :title do + 'foo' + end + content_for :title, nil, true do + 'bar' + end + assert_equal 'bar', content_for(:title) + end + + def test_content_for_with_block_and_multiple_calls_without_flush + assert ! content_for?(:title) + content_for :title do + 'foo' + end + content_for :title, false do + 'bar' + end + assert_equal 'foobar', content_for(:title) + end + def test_content_for_with_whitespace_block assert ! content_for?(:title) content_for :title, 'foo' @@ -74,12 +114,27 @@ def test_content_for_with_whitespace_block assert_equal 'foobar', content_for(:title) end + def test_content_for_with_whitespace_block_and_flush + assert ! content_for?(:title) + content_for :title, 'foo' + content_for :title, true do + output_buffer << " \n " + nil + end + content_for :title, 'bar', true + assert_equal 'bar', content_for(:title) + end + def test_content_for_returns_nil_when_writing assert ! content_for?(:title) assert_equal nil, content_for(:title, 'foo') assert_equal nil, content_for(:title) { output_buffer << 'bar'; nil } assert_equal nil, content_for(:title) { output_buffer << " \n "; nil } assert_equal 'foobar', content_for(:title) + assert_equal nil, content_for(:title, 'foo', true) + assert_equal nil, content_for(:title, true) { output_buffer << 'bar'; nil } + assert_equal nil, content_for(:title, true) { output_buffer << " \n "; nil } + assert_equal 'bar', content_for(:title) end def test_content_for_question_mark