pass yielded arguments to block for ActionView::Base#render with :layout [#847 state:resolved]
Signed-off-by: Joshua Peek <josh@joshpeek.com>
This commit is contained in:
parent
dbb0abfb7e
commit
38c7d73e73
@ -246,12 +246,18 @@ def render(options = {}, local_assigns = {}, &block) #:nodoc:
|
||||
|
||||
if partial_layout = options.delete(:layout)
|
||||
if block_given?
|
||||
wrap_content_for_layout capture(&block) do
|
||||
begin
|
||||
@_proc_for_layout = block
|
||||
concat(render(options.merge(:partial => partial_layout)))
|
||||
ensure
|
||||
@_proc_for_layout = nil
|
||||
end
|
||||
else
|
||||
wrap_content_for_layout render(options) do
|
||||
begin
|
||||
original_content_for_layout, @content_for_layout = @content_for_layout, render(options)
|
||||
render(options.merge(:partial => partial_layout))
|
||||
ensure
|
||||
@content_for_layout = original_content_for_layout
|
||||
end
|
||||
end
|
||||
elsif options[:file]
|
||||
@ -367,13 +373,6 @@ def render_inline(text, local_assigns = {}, type = nil)
|
||||
InlineTemplate.new(text, type).render(self, local_assigns)
|
||||
end
|
||||
|
||||
def wrap_content_for_layout(content)
|
||||
original_content_for_layout, @content_for_layout = @content_for_layout, content
|
||||
yield
|
||||
ensure
|
||||
@content_for_layout = original_content_for_layout
|
||||
end
|
||||
|
||||
# Evaluate the local assigns and pushes them to the view.
|
||||
def evaluate_assigns
|
||||
unless @assigns_added
|
||||
@ -392,11 +391,5 @@ def set_controller_content_type(content_type)
|
||||
controller.response.content_type ||= content_type
|
||||
end
|
||||
end
|
||||
|
||||
def execute(method, local_assigns = {})
|
||||
send(method, local_assigns) do |*names|
|
||||
instance_variable_get "@content_for_#{names.first || 'layout'}"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -68,7 +68,7 @@ module ActionView
|
||||
#
|
||||
# <%# app/views/users/_editor.html.erb &>
|
||||
# <div id="editor">
|
||||
# Deadline: $<%= user.deadline %>
|
||||
# Deadline: <%= user.deadline %>
|
||||
# <%= yield %>
|
||||
# </div>
|
||||
#
|
||||
@ -82,7 +82,7 @@ module ActionView
|
||||
#
|
||||
# Here's the editor:
|
||||
# <div id="editor">
|
||||
# Deadline: $<%= user.deadline %>
|
||||
# Deadline: <%= user.deadline %>
|
||||
# Name: <%= user.name %>
|
||||
# </div>
|
||||
#
|
||||
@ -101,6 +101,40 @@ module ActionView
|
||||
# </div>
|
||||
#
|
||||
# As you can see, the <tt>:locals</tt> hash is shared between both the partial and its layout.
|
||||
#
|
||||
# If you pass arguments to "yield" then this will be passed to the block. One way to use this is to pass
|
||||
# an array to layout and treat it as an enumerable.
|
||||
#
|
||||
# <%# app/views/users/_user.html.erb &>
|
||||
# <div class="user">
|
||||
# Budget: $<%= user.budget %>
|
||||
# <%= yield user %>
|
||||
# </div>
|
||||
#
|
||||
# <%# app/views/users/index.html.erb &>
|
||||
# <% render :layout => @users do |user| %>
|
||||
# Title: <%= user.title %>
|
||||
# <% end %>
|
||||
#
|
||||
# This will render the layout for each user and yield to the block, passing the user, each time.
|
||||
#
|
||||
# You can also yield multiple times in one layout and use block arguments to differentiate the sections.
|
||||
#
|
||||
# <%# app/views/users/_user.html.erb &>
|
||||
# <div class="user">
|
||||
# <%= yield user, :header %>
|
||||
# Budget: $<%= user.budget %>
|
||||
# <%= yield user, :footer %>
|
||||
# </div>
|
||||
#
|
||||
# <%# app/views/users/index.html.erb &>
|
||||
# <% render :layout => @users do |user, section| %>
|
||||
# <%- case section when :header -%>
|
||||
# Title: <%= user.title %>
|
||||
# <%- when :footer -%>
|
||||
# Deadline: <%= user.deadline %>
|
||||
# <%- end -%>
|
||||
# <% end %>
|
||||
module Partials
|
||||
extend ActiveSupport::Memoizable
|
||||
|
||||
|
@ -31,7 +31,14 @@ def render(view, local_assigns = {})
|
||||
|
||||
view.send(:evaluate_assigns)
|
||||
view.send(:set_controller_content_type, mime_type) if respond_to?(:mime_type)
|
||||
view.send(:execute, method_name(local_assigns), local_assigns)
|
||||
|
||||
view.send(method_name(local_assigns), local_assigns) do |*names|
|
||||
if proc = view.instance_variable_get("@_proc_for_layout")
|
||||
view.capture(*names, &proc)
|
||||
else
|
||||
view.instance_variable_get("@content_for_#{names.first || 'layout'}")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def method_name(local_assigns)
|
||||
|
@ -41,19 +41,19 @@ def setup
|
||||
|
||||
@request.host = "www.nextangle.com"
|
||||
end
|
||||
|
||||
|
||||
def test_application_layout_is_default_when_no_controller_match
|
||||
@controller = ProductController.new
|
||||
get :hello
|
||||
assert_equal 'layout_test.rhtml hello.rhtml', @response.body
|
||||
end
|
||||
|
||||
|
||||
def test_controller_name_layout_name_match
|
||||
@controller = ItemController.new
|
||||
get :hello
|
||||
assert_equal 'item.rhtml hello.rhtml', @response.body
|
||||
end
|
||||
|
||||
|
||||
def test_third_party_template_library_auto_discovers_layout
|
||||
ThirdPartyTemplateLibraryController.view_paths.reload!
|
||||
@controller = ThirdPartyTemplateLibraryController.new
|
||||
@ -63,14 +63,14 @@ def test_third_party_template_library_auto_discovers_layout
|
||||
assert_response :success
|
||||
assert_equal 'Mab', @response.body
|
||||
end
|
||||
|
||||
|
||||
def test_namespaced_controllers_auto_detect_layouts
|
||||
@controller = ControllerNameSpace::NestedController.new
|
||||
get :hello
|
||||
assert_equal 'layouts/controller_name_space/nested', @controller.active_layout
|
||||
assert_equal 'controller_name_space/nested.rhtml hello.rhtml', @response.body
|
||||
end
|
||||
|
||||
|
||||
def test_namespaced_controllers_auto_detect_layouts
|
||||
@controller = MultipleExtensions.new
|
||||
get :hello
|
||||
@ -115,7 +115,7 @@ def test_add_regexp_to_exempt_from_layout
|
||||
|
||||
def test_rhtml_exempt_from_layout_status_should_prevent_layout_render
|
||||
ActionController::Base.exempt_from_layout :rhtml
|
||||
|
||||
|
||||
assert @controller.send!(:template_exempt_from_layout?, 'test.rhtml')
|
||||
assert @controller.send!(:template_exempt_from_layout?, 'hello.rhtml')
|
||||
|
||||
@ -156,19 +156,19 @@ def test_layout_set_when_using_default_layout
|
||||
get :hello
|
||||
assert_equal 'layouts/layout_test', @response.layout
|
||||
end
|
||||
|
||||
|
||||
def test_layout_set_when_set_in_controller
|
||||
@controller = HasOwnLayoutController.new
|
||||
get :hello
|
||||
assert_equal 'layouts/item', @response.layout
|
||||
end
|
||||
|
||||
|
||||
def test_layout_set_when_using_render
|
||||
@controller = SetsLayoutInRenderController.new
|
||||
get :hello
|
||||
assert_equal 'layouts/third_party_template_library', @response.layout
|
||||
end
|
||||
|
||||
|
||||
def test_layout_is_not_set_when_none_rendered
|
||||
@controller = RendersNoLayoutController.new
|
||||
get :hello
|
||||
@ -249,4 +249,3 @@ def test_symlinked_layout_is_rendered
|
||||
assert_equal "layouts/symlinked/symlinked_layout", @response.layout
|
||||
end
|
||||
end
|
||||
|
@ -435,6 +435,10 @@ def render_using_layout_around_block
|
||||
render :action => "using_layout_around_block"
|
||||
end
|
||||
|
||||
def render_using_layout_around_block_with_args
|
||||
render :action => "using_layout_around_block_with_args"
|
||||
end
|
||||
|
||||
def render_using_layout_around_block_in_main_layout_and_within_content_for_layout
|
||||
render :action => "using_layout_around_block"
|
||||
end
|
||||
@ -969,4 +973,9 @@ def test_using_layout_around_block_in_main_layout_and_within_content_for_layout
|
||||
get :render_using_layout_around_block_in_main_layout_and_within_content_for_layout
|
||||
assert_equal "Before (Anthony)\nInside from first block in layout\nAfter\nBefore (David)\nInside from block\nAfter\nBefore (Ramm)\nInside from second block in layout\nAfter\n", @response.body
|
||||
end
|
||||
|
||||
def test_using_layout_around_block_with_args
|
||||
get :render_using_layout_around_block_with_args
|
||||
assert_equal "Before\narg1arg2\nAfter", @response.body
|
||||
end
|
||||
end
|
||||
|
3
actionpack/test/fixtures/test/_layout_for_block_with_args.html.erb
vendored
Normal file
3
actionpack/test/fixtures/test/_layout_for_block_with_args.html.erb
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
Before
|
||||
<%= yield 'arg1', 'arg2' %>
|
||||
After
|
1
actionpack/test/fixtures/test/using_layout_around_block_with_args.html.erb
vendored
Normal file
1
actionpack/test/fixtures/test/using_layout_around_block_with_args.html.erb
vendored
Normal file
@ -0,0 +1 @@
|
||||
<% render(:layout => "layout_for_block_with_args") do |*args| %><%= args.join %><% end %>
|
Loading…
Reference in New Issue
Block a user