I am currently working on a rails app that has a common pattern on fields throughout many forms and many fields of the same form. This is the pattern:
<%= simple_form_for(@evaluation) do |f| %>
<%= f.error_notification %>
<div class="toggle">
<div class="toggle_selector">
<%= f.input :was_answered, :as => :radio, :collection => [:yes, :no, '?'] %>
</div>
<div class="toggle_content">
<%= f.input :name %>
<%= f.input :answer %>
<%= f.input :score %>
</div>
</div>
<div class="actions">
<%= f.button :submit %>
</div>
<% end %>
There is a main div tag that surrounds two other divs. The toggle_content div is made visible or not, using javascript, based on the value from the input that is in toggle_selector div.
I tried to extract a couple helpers that would take the inputs as parametes and output the desired output:
def toggling_field_for form, selector, &block
content_tag :div, :class => 'toggle' do
%{#{toggle_selector form, selector}
#{toggle_content &block if block_given?}
}.html_safe
end
end
private
def toggle_selector form, selector
content_tag :div, :class => 'toggle_selector' do
form.input selector, :as => :radio, :collection => [:yes, :no, '?']
end
end
def toggle_content
content_tag :div, :class => 'toggle_content' do
yield if block_given?
end
end
However, this will only work if i only have one input on the toggle_content div, because when i use the yield on the block of inputs, only the last one will be output.
Anyone could give a hint on a better solution to refactor these to be able to accept more than one input on the toggle_content div?
Edited: Problem solved using the capture helper method instead of just yield. The code ended up like this on the helper:
def toggling_field_for form, selector, &block
content_tag :div, :class => 'toggle' do
%{#{toggle_selector form, selector}
#{toggle_content &block}
}.html_safe
end
end
private
def toggle_content &block
content_tag :div, capture(&block), :class => 'toggle_content'
end
And called like this on each form:
<%= toggling_field_for f, :was_answered, do %>
<%= f.input :name %>
<%= f.input :answer %>
<%= f.input :score %>
<% end %>
Thanks, mosch!
With Rails 3, your code should work with a slight modification: Try changing
to
I am not sure, but you can probably remove the block_given? clause in that case.