It turns out that the syntax used in fields_for to allow a block embedded in ERB is remarkably simple. I ripped the guts out of form_for and used it's basic block logic to power my own helper that I called, simply 'section'. First, here's the view now that I can use a block:
<% section 'Strength' do %>
<%= data :forty_time, 'Forty time' %>
<%= data :bench_press, 'Bench Press (Max)' %>
<%= data :squat_max, 'Squat (Max)' %>
<%= data :clean_max, 'Clean (Max)' %>
<% end %>
Way, way, way cleaner. The best part about this is that it's actually semantic. I'm specifying that I want to start a block named 'Strength' and I'm going to put an arbitrary number of elements into it. Am I going to use an unordered list? Doesn't matter! I can leave that to the helper and keep a single point of code maintenance.
So let's take a look at the super-complicated (as Ruby always is) method that allows this. Here's my updated helper:
module AthletesHelper
def section(name, &proc)
raise ArgumentError, "Missing block" unless block_given?
concat('', proc.binding)
concat(content_tag(:h2, name), proc.binding)
yield # this is where the stuff in the block get's eval'd and inserted
concat('
', proc.binding)
end
def data(att, label)
content_tag(:li, content_tag(:label, label)+
content_tag(:div, @athlete_contact.send(att),
:id => "contact_#{att.to_s}",
:class => 'data'))
end
end
It's that simple.
You may find the part about concat('text', proc.binding) a little confusing - I certainly did. I won't try to pretend I completely graps it except to say that when *concat* is passed proc.binding it executes the code in the environment of the proc. In other words,
concat('', proc.binding)
is the same as having typed
<%= '' %>
-
jc said:
I've been doing this for a while, but found it horribly ugly. I've recently found a better way. The only problem is you need to use haml
open :ul, {:class => "section"} do
open :h2, name
yield
end
if you want to output random text, you just use the "puts" within the block
so the .html.haml would be
- section 'Strength' do
= data :forty_time, 'Forty time'
= data :bench_press, 'Bench Press (Max)'
= etc...
blog comments powered by Disqus