Lighthouse has a new layout. Prefer the old one? Return to the old layout, and switch back any time from the link at the top of each page.

This project is archived and is in readonly mode.

Parts of template are rendered twice, induced by yield or cache

#6148

When I use a helper method, that yields to a given content block, the surrounding(!) template is rendered twice above where the helper is used. Rails 3.0.3.

Standard layout:

<!DOCTYPE html>
<html>
<head>
  <title>Foo</title>
  <%= stylesheet_link_tag :all %>
  <%= javascript_include_tag :defaults %>
  <%= csrf_meta_tag %>
</head>
<body>

<%= yield %>

</body>
</html>

Helper:

def foo(&block)
  yield
end

Template:

<p>TOP</p>

<%- foo do -%>
<p>YIELDED STUFF</p>
<%- end -%>

<p>BOTTOM</p>

Output:

TOP
YIELDED STUFF
TOP
YIELDED STUFF
BOTTOM

I'm having this same issue with cache do:

<p>TOP</p>

<%- if false; cache do -%>
Something
<%- end; else -%>
foobar
<%- end -%>

<p>BOTTOM</p>

Output:

TOP
foobar
TOP
foobar
BOTTOM

The double rendering does NOT occur like this:

<p>TOP</p>

<%- if false -%>
Something - without cache
<%- else -%>
foobar
<%- end -%>

<p>BOTTOM</p>

Or this:

<p>TOP</p>

<%- if true; cache do -%>
Something - note the TRUE in this version
<%- end; else -%>
Bar
<%- end -%>

<p>BOTTOM</p>

Reported by Jan · December 11th, 2010 @ 12:29 PM

State: invalid
Milestone: none
Assigned to: nobody
Importance: Low

Activity

  1. Piotr Sarnacki
    Piotr Sarnacki
    • Importance changed from to Low

    You need to use capture in your helper:

    def foo(&block)
      capture(&block)
    end
    

    And add = in front of the call in view:

    <%= foo do -%>
      Something
    <% end -%>
    

    As of second example, I think that this is based on implementation of <%= block_helper do %> in Rails 3:
    https://github.com/rails/rails/blob/master/actionpack/lib/action_vi...

    I don't know if this can be fixed, as for now you should use that form:

    <%- if false -%>
      <%= cache do -%>
        Something
      <%- end -%>
    <%- else -%>
     foobar
    <%- end -%>
    

    December 11th, 2010 @ 02:37 PM

  2. Jan
    Jan

    Well, the cache thing was my real problem, the other one was just how I tried to understand what might be going wrong. So thanks for pointing out my mistakes! I already went a little crazy.

    December 12th, 2010 @ 08:21 AM

  3. Jan
  4. Piotr Sarnacki
    Piotr Sarnacki
    • State changed from new to invalid

    I think that cache works both with = and without, probably it just writes to @output_buffer and returns nil, so = does not change anything. I just thought that it needs it. Seems like a little bit inconsistent, though.

    I think this can be closed and I'll start a discussion on block helpers on rails group later.

    December 12th, 2010 @ 10:23 AM