Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Capturing and rendering a block as string in an ERB template. Is this possible? #77

Open
mhayes opened this issue Mar 6, 2013 · 5 comments

Comments

@mhayes
Copy link

mhayes commented Mar 6, 2013

Just curious, but is it possible to create a helper that captures the content of a block. Specifically I'd love to be able to do something like this in Stasis (this is a simplified example):

In my ERB template:

<% show_for_version('4.0.0') do %>
<p>I would love to display HTML content here.</p>
<% end %>

I would like the HTML output to then look something like this:

<div class='version-4.0.4'>
  <p>I would love to display HTML content here.</p>
</div>

I tried to implement this as a helper method in controller.rb but it does not seem to be doing anything. Here's the helper code I have:

helper do
  def show_for_version(version, &block)
    if block_given?
      "<div class='version-#{version}'>#{yield block}</div>"
    end
  end
end

Is something like this possible? Any help would be mucho appreciated, thanks!

@mhayes
Copy link
Author

mhayes commented Mar 6, 2013

I forgot to mention that Stasis is awesome! We're using it to power the documentation for Foundation. Keep up the great work!

@rudolfochrist
Copy link

To keep a long answer short: Yes it is possible. But it takes some effort.

As Jay Fields has pointed out, you have to tell ERB where to store the output and then concat it yourself. Currently I have no idea how to do this with stasis, because my knowledge of the code is very limited (yet).

Alternatively you can come up with a capture helper like Rails. This would also be interesting for a future release of stasis.

I hope this helps because I'm not really providing a solution to your problem.

@mhayes
Copy link
Author

mhayes commented Mar 12, 2013

Thanks @rudolfochrist for pointing me in the right direction. I think I may have found something, but it's not working quite as expected. Here's an example project that I setup to demonstrate how this could potentially work:

https://github.com/mhayes/stasis-erb-blocks

The magic is a combination of a capture helper taken from Nanoc and printing the ERB result to the block's binding here:

https://github.com/mhayes/stasis-erb-blocks/blob/master/controller.rb#L35

However some of the ERB output is being truncated. So here's what I expect to render in this project:

<!doctype html>
<html>
  <body>
<div class="row">
  <div class="twelve columns">
    <h2>Lorem Ipsum</h2>
    <div class='test-wrapper'>
      <p>This is code!</p>
    </div>

    <p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.</p>
  </div>
</div>
  </body>
</html>

And here's what actually renders:

<!doctype html>
<html>
  <body>
    <div class='test-wrapper'>
      <p>This is code!</p>
    </div>

    <p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.</p>
  </div>
</div>
  </body>
</html>

So it appears that the beginning output in the index.html.erb template is simply being truncated. Any ideas @rudolfochrist on how to fix this? If we can figure this out I'd love to find a way to create a PR for Stasis to support this going forward.

Cheers!

@rudolfochrist
Copy link

Hi @mhayes,

it seems that the new ERB object dismisses the already existing _erbout buffer. The only way I had success, was in changing the code_block helper directly to this:

def code_block(&block)
  erbout = block.binding.eval('_erbout')
  erbout << '<div class="test-wrapper">'
  yield
  erbout << '</div>'
end

But this is kinda ugly. An elegantly solution would be to put the logic directly into stasis itself with a custom output buffer. With that you can use a tmp buffer while the block is executed and restore the previous output when the block has finished.

@mhayes
Copy link
Author

mhayes commented Mar 19, 2013

Thanks @rudolfochrist, I'll give that a try. Cheers!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants