Helpers and Blocks
February 22nd, 2007
In rails 1.2 a new kind of helper was introduced with form_tag. This helper method not only takes a block, but wraps content around that block, even though it’s called with <% %> rather than <%= %>. Odd, but ever so useful.
Here’s how to write your own helper that can take a block of ERb.
Say you want to wrap a bunch of random content in a div that hides itself when clicked. And this div usually has a title. Here’s what the usage would look like:
1 2 3 |
<% hiding_div "Snazzy!" do %> Text and and a logo <%= image_tag "some_img.png" %> <% end %> |
Which should yield:
1 2 3 4 |
<div onclick="this.hide();"> <h2>Snazzy!</h2> Text and and a logo <img src="/images/some_img.png" /> </div> |
So first we have to think about how ERb renders your template. ERb converts all your static bits to strings, then executes the ruby bits, and converts those to strings. Then it calls the concat('some_string') method which appends each string the output of the ERb render. So we have to use concat in our helper, since our helper won’t be called with <%= %>.
1 2 3 4 5 6 7 8 9 |
def hiding_div(title = nil, &block) html = <<-HTML <div onclick="this.hide();"> #{content_tag :h2, title unless title.blank?} #{capture(&block)} </div> HTML concat(html, block.binding) end |
Two things here to note.
- The
capturemethod.capturewill execute a chunk of ERb and return it as a string. This allows us to, well, capture the result of the block without writing it the output stream. concatandblock.binding. Now that we have generated the proper output, we have to write it the page output that is currently being rendered.concatdoes this, but if we just doconcat('foo')it will fail from the helper. This because there is no ERb output stream in our helper. The output stream is in the template. By passingblock.bindingtoconcatwe tell theconcatoperation to happen in the place where the block was created (bound), in this case, the template.
It’s not that hard to make helpers that take ERb chunks. And it has all kinds of usefulness. Play with it.
Anyone else have any useful block helpers?
June 28th, 2007 at 11:05 PM
Nice one, thank you. I’m working on something and you just provided the base of my solution.