Skip to content

Instantly share code, notes, and snippets.

@ernie
Created July 14, 2010 12:46
Show Gist options
  • Save ernie/475368 to your computer and use it in GitHub Desktop.
Save ernie/475368 to your computer and use it in GitHub Desktop.
module ActionView
module Helpers
class FormBuilder
Check = Struct.new(:box, :label)
# Behaves almost exactly like the select method, but instead of generating a select tag,
# generates Checks. These consist of two attributes, +box+ and +label+,
# which are (unsurprisingly) the HTML for the check box and the label. Called without a block,
# this method will return an array of check boxes. Called with a block, it will yield each
# check box to your template.
#
# *Parameters:*
#
# * +method+ - The method name on the form_for object
# * +choices+ - An array of arrays, the first value in each element is the text for the
# label, and the last is the value for the checkbox
# * +options+ - An options hash to be passed through to the checkboxes
#
# *Examples:*
#
# <b>Simple formatting:</b>
#
# <h4>How many heads?</h4>
# <ul>
# <% f.check_boxes :number_of_heads_in,
# [['One', 1], ['Two', 2], ['Three', 3]], :class => 'checkboxy' do |check| %>
# <li>
# <%= check.box %>
# <%= check.label %>
# </li>
# <% end %>
# </ul>
#
# This example will output the checkboxes and labels in an unordered list format.
#
# <b>Grouping:</b>
#
# Chain <tt>in_groups_of(<num>, false)</tt> on check_boxes like so:
# <h4>How many heads?</h4>
# <p>
# <% f.check_boxes(:number_of_heads_in,
# [['One', 1], ['Two', 2], ['Three', 3]],
# :class => 'checkboxy').in_groups_of(2, false) do |checks| %>
# <% checks.each do |check| %>
# <%= check.box %>
# <%= check.label %>
# <% end %>
# <br />
# <% end %>
# </p>
def check_boxes(method, choices = [], options = {}, &block)
unless choices.first.respond_to?(:first) && choices.first.respond_to?(:last)
raise ArgumentError, 'invalid choice array specified'
end
collection_check_boxes(method, choices, :last, :first, options, &block)
end
# Just like +check_boxes+, but this time you can pass in a collection, value, and text method,
# as with collection_select.
#
# Example:
#
# <% f.collection_check_boxes :head_sizes_in, HeadSize.all,
# :id, :name, :class => 'headcheck' do |check| %>
# <%= check.box %> <%= check.label %>
# <% end %>
def collection_check_boxes(method, collection, value_method, text_method, options = {}, &block)
check_boxes = []
collection.each do |choice|
text = choice.send(text_method)
value = choice.send(value_method)
check = Check.new
check.box = @template.check_box_tag(
"#{@object_name}[#{method}][]",
value,
[@object.send(method)].flatten.include?(value),
options.merge(:id => [@object_name, method.to_s, value.to_s.underscore].join('_'))
)
check.label = @template.label_tag([@object_name, method.to_s, value.to_s.underscore].join('_'),
text)
if block_given?
yield check
else
check_boxes << check
end
end
check_boxes unless block_given?
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment