Skip to content

Commit

Permalink
Fix issue with rendering partials and then yielding inside a render l…
Browse files Browse the repository at this point in the history
…ayout call

The given block was never being executed when another render :partial call
existed before the yield call, due to the block being overriden.

This commit also adds some more tests to render with :layout option.

Signed-off-by: José Valim <jose.valim@gmail.com>
  • Loading branch information
carlosantoniodasilva authored and josevalim committed Nov 11, 2010
1 parent 55a8bd6 commit 3e86e4b
Show file tree
Hide file tree
Showing 6 changed files with 36 additions and 11 deletions.
22 changes: 11 additions & 11 deletions actionpack/lib/action_view/render/partials.rb
Expand Up @@ -30,31 +30,31 @@ module ActionView
# #
# By default PartialRenderer uses the template name for the local name of the object passed into the template. # By default PartialRenderer uses the template name for the local name of the object passed into the template.
# These examples are effectively the same: # These examples are effectively the same:
# #
# <%= render :partial => "contract", :locals => { :contract => @contract } %> # <%= render :partial => "contract", :locals => { :contract => @contract } %>
# #
# <%= render :partial => "contract" %> # <%= render :partial => "contract" %>
# #
# By specifying the :as option we can change the way the local variable is namedin the template. # By specifying the :as option we can change the way the local variable is namedin the template.
# These examples are effectively the same: # These examples are effectively the same:
# #
# <%= render :partial => "contract", :as => :agreement # <%= render :partial => "contract", :as => :agreement
# #
# <%= render :partial => "contract", :locals => { :agreement => @contract } # <%= render :partial => "contract", :locals => { :agreement => @contract }
# #
# The :object option can be used to directly specify which object is rendered into the partial. # The :object option can be used to directly specify which object is rendered into the partial.
# #
# Revisiting a previous example we could have written this code. # Revisiting a previous example we could have written this code.
# #
# <%= render :partial => "account", :object => @buyer %> # <%= render :partial => "account", :object => @buyer %>
# #
# <% for ad in @advertisements %> # <% for ad in @advertisements %>
# <%= render :partial => "ad", :object => ad %> # <%= render :partial => "ad", :object => ad %>
# <% end %> # <% end %>
# #
# The :object and :as options can be used together. We might have a partial which we have named genericly, # The :object and :as options can be used together. We might have a partial which we have named genericly,
# such as 'form'. Using :object and :as together helps us. # such as 'form'. Using :object and :as together helps us.
# #
# <%= render :partial => "form", :object => @contract, :as => :contract %> # <%= render :partial => "form", :object => @contract, :as => :contract %>
# == Rendering a collection of partials # == Rendering a collection of partials
# #
Expand All @@ -70,7 +70,7 @@ module ActionView
# +partial_name_counter+. In the case of the example above, the template would be fed +ad_counter+. # +partial_name_counter+. In the case of the example above, the template would be fed +ad_counter+.
# #
# The :as option may be used when rendering partials. # The :as option may be used when rendering partials.
# #
# Also, you can specify a partial which will be render as a spacer between each element by passing partial name to # Also, you can specify a partial which will be render as a spacer between each element by passing partial name to
# +:spacer_template+. The following example will render "advertiser/_ad_divider.erb" between each ad partial. # +:spacer_template+. The following example will render "advertiser/_ad_divider.erb" between each ad partial.
# #
Expand Down Expand Up @@ -323,13 +323,13 @@ def collection_without_template(collection_paths = @collection_paths)
end end


def render_partial(object = @object) def render_partial(object = @object)
locals, view, template = @locals, @view, @template locals, view, template, block = @locals, @view, @template, @block


object ||= locals[template.variable_name] object ||= locals[template.variable_name]
locals[@options[:as] || template.variable_name] = object locals[@options[:as] || template.variable_name] = object


template.render(view, locals) do |*name| template.render(view, locals) do |*name|
view._layout_for(*name, &@block) view._layout_for(*name, &block)
end end
end end


Expand Down
2 changes: 2 additions & 0 deletions actionpack/test/fixtures/layouts/_partial_and_yield.erb
@@ -0,0 +1,2 @@
<%= render :partial => 'test/partial' %>
<%= yield %>
1 change: 1 addition & 0 deletions actionpack/test/fixtures/layouts/_yield_only.erb
@@ -0,0 +1 @@
<%= yield %>
1 change: 1 addition & 0 deletions actionpack/test/fixtures/layouts/_yield_with_params.erb
@@ -0,0 +1 @@
<%= yield 'Yield!' %>
@@ -0,0 +1,2 @@
<%= render :partial => 'test/partial' %>
<%= yield %>
19 changes: 19 additions & 0 deletions actionpack/test/template/render_test.rb
Expand Up @@ -238,6 +238,25 @@ def test_render_with_layout_which_has_render_inline
@view.render(:file => "test/hello_world.erb", :layout => "layouts/yield_with_render_inline_inside") @view.render(:file => "test/hello_world.erb", :layout => "layouts/yield_with_render_inline_inside")
end end


def test_render_with_layout_which_renders_another_partial
assert_equal %(partial html\nHello world!\n),
@view.render(:file => "test/hello_world.erb", :layout => "layouts/yield_with_render_partial_inside")
end

def test_render_layout_with_block_and_yield
assert_equal %(Content from block!\n),
@view.render(:layout => "layouts/yield_only") { "Content from block!" }
end

def test_render_layout_with_block_and_yield_with_params
assert_equal %(Yield! Content from block!\n),
@view.render(:layout => "layouts/yield_with_params") { |param| "#{param} Content from block!" }
end

def test_render_layout_with_block_which_renders_another_partial_and_yields
assert_equal %(partial html\nContent from block!\n),
@view.render(:layout => "layouts/partial_and_yield") { "Content from block!" }
end


# TODO: Move to deprecated_tests.rb # TODO: Move to deprecated_tests.rb
def test_render_with_nested_layout_deprecated def test_render_with_nested_layout_deprecated
Expand Down

0 comments on commit 3e86e4b

Please sign in to comment.