Reputation: 5613
I would like to define some helper methods within a block helper but keep them within the scope of the block so that I can have sensible method names and it looks cleaner.
Say I want to do the following (a very basic example), in my view using helpers:
<%= foo_box do |b| %>
<%= b.title( 'Foo Bar' ) %>
Lorem Ipsum...
<% end %>
To produce something like
<div class="foo_box">
<h2>Foo Bar</h2>
Lorem Ipsum...
</div>
This way I could also have a bar_box
block helper which could also have a title
method which outputs something totally different.
Currently I have them implemented as different methods, e.g. foo_box
and foo_box_title
, with foo_box
handling the block like so:
def foo_box(&block)
content_tag(:div, capture(&block), :class => 'foo_box')
end
Upvotes: 4
Views: 687
Reputation: 1725
By the looks of it, capture
doesn't let you pass any arguments into the block, which you want to do. The argument to bass in (b
) has to be an object of some sort that you define the title
etc. methods on. So, lets define a helper class which will output the stuff you need, and pass it to the block passed in from the view, and then capture it and surround it in the div
as you did above. I would do something like this:
class FooBoxHelper
include ActionView::Helpers::TagHelper
def title(text)
content_tag(:h2, text)
end
def small(text)
content_tag(:p, text, :class => "small")
end
end
def foo_box(&block)
new_block = Proc.new do
helper = FooBoxHelper.new
block.call(helper)
end
content_tag(:div, capture(&new_block), :class => 'foo_box')
end
See how I got around the limitation of the capture
method? By binding a new Proc to the current scope, and passing in the helper object there, we get a block we can call with no arguments, and thus acceptable by capture
. Also, make certain your helper class includes all the relevant helper methods from ActionView::Helpers
. Hope this helps!
Upvotes: 5