Richer Helpers
I learned a little about how ERb works today. What I've been trying to do is create a helper method that allows me to output a complex layout element (multiple div) and pass it an ERb block in my HTML template, but have the helper wrap its code around the block, much like the
What does this do exactly?
I love how Rails has allowed me to gradually discover more about the Ruby language and become more adept at using its advanced features. While I don't completely understand Procs and blocks and all of that, I'm much closer now.
form_for
method. I planned to use the XML Builder since it provides nice semantics and visually beautiful code. I thought at first that it would be as simple as using yield
in the middle of my helper. I struggled with this for quite a while, but I finally discovered that when Rails encounters the block, it's going to output it to the browser automatically, even if that block is passed to the method. The solution was to use a capture
, then steal a little trick from form_for
: the concat(text, context)
method. Here's some sample code:
# In your helper class
def complex_layout(..., &block) # &block last in params
raise ArgumentError, "Missing block" unless block_given?
buffer = capture(&block)
xm = Builder::XmlMarkup.new
xm.div {
...
# the point of your layout
# where you want the passed block to appear
xm << buffer
...
}
concat(xm.target!, block.binding)
end
What does this do exactly?
- The
raise
statement requires that a block is passed. - The
capture
statement stores the ERb output of the block intobuffer
. - The next set of statements create the Builder and construct the markup.
- The
xm << buffer
statement pushes the contents ofbuffer
into your Builder markup without escaping the contents - Finally,
concat
uses the block's binding (calling context) to output the contents of the Builder markup.
I love how Rails has allowed me to gradually discover more about the Ruby language and become more adept at using its advanced features. While I don't completely understand Procs and blocks and all of that, I'm much closer now.