Adding collection checkbox, adding checked and disabled options for collection radio and fix association name when dealing with has_*.

This commit is contained in:
Carlos Antonio da Silva 2009-12-11 13:09:00 -02:00
parent 74014e2743
commit 9000830e19
5 changed files with 212 additions and 19 deletions

View File

@ -8,27 +8,98 @@ module SimpleForm
# helper will create a radio input associated with a label for each
# text/value option in the collection, using value_method and text_method
# to convert these text/value. Based on collection_select.
# Example:
#
# == Examples
#
# form_for @user do |f|
# f.collection_radio :active, [['Yes', true] ,['No', false]], :first, :last
# f.collection_radio :options, [[true, 'Yes'] ,[false, 'No']], :first, :last
# end
#
# <input id="user_active_true" name="user[active]" type="radio" value="true" />
# <label class="radio" for="user_active_true">Yes</label>
# <input id="user_active_false" name="user[active]" type="radio" value="false" />
# <label class="radio" for="user_active_false">No</label>
# <input id="user_options_true" name="user[options]" type="radio" value="true" />
# <label class="collection_radio" for="user_options_true">Yes</label>
# <input id="user_options_false" name="user[options]" type="radio" value="false" />
# <label class="collection_radio" for="user_options_false">No</label>
#
def collection_radio(attribute, collection, value_method, text_method, html_options={})
# == Options
#
# Collection radio accepts some extra options:
#
# * checked => the value that should be checked initially.
#
# * disabled => the value or values that should be disabled. Accepts a single
# item or an array of items.
#
def collection_radio(attribute, collection, value_method, text_method, options={}, html_options={})
checked_option = options.delete(:checked)
disabled_options = Array(options.delete(:disabled))
collection.inject('') do |result, item|
value = item.send value_method
text = item.send text_method
result << radio_button(attribute, value, html_options) <<
checked = checked_option == value if checked_option
disabled = disabled_options.include?(value)
default_html_options = html_options.dup
default_html_options[:checked] = checked if checked
default_html_options[:disabled] = disabled if disabled
result << radio_button(attribute, value, default_html_options) <<
label("#{attribute}_#{value}", text, :class => "collection_radio")
end
end
# Creates a collection of check boxes for each item in the collection, associated
# with a clickable label. Use value_method and text_method to convert items in
# the collection for use as text/value in check boxes.
#
# == Examples
#
# form_for @user do |f|
# f.collection_check_box :options, [[true, 'Yes'] ,[false, 'No']], :first, :last
# end
#
# <input name="user[options][]" type="hidden" value="" />
# <input id="user_options_true" name="user[options][]" type="checkbox" value="true" />
# <label class="collection_check_box" for="user_options_true">Yes</label>
# <input name="user[options][]" type="hidden" value="" />
# <input id="user_options_false" name="user[options][]" type="checkbox" value="false" />
# <label class="collection_check_box" for="user_options_false">No</label>
#
# == Options
#
# Collection check box accepts some extra options:
#
# * checked => the value or values that should be checked initially. Accepts
# a single item or an array of items.
#
# * disabled => the value or values that should be disabled. Accepts a single
# item or an array of items.
#
def collection_check_box(attribute, collection, value_method, text_method, options={}, html_options={})
checked_options = Array(options.delete(:checked))
disabled_options = Array(options.delete(:disabled))
collection.inject('') do |result, item|
value = item.send value_method
text = item.send text_method
input_name = "#{object_name}[#{attribute}][]"
input_id = "#{object_name}_#{attribute}_#{value}"
checked = checked_options.include?(value)
disabled = disabled_options.include?(value)
default_html_options = html_options.dup
default_html_options[:id] = input_id
default_html_options[:name] = input_name
default_html_options[:checked] = checked if checked
default_html_options[:disabled] = disabled if disabled
result << check_box(attribute, default_html_options, value, '') <<
label("#{attribute}_#{value}", text, :class => "collection_check_box")
end
end
# Wrapper for using simple form inside a default rails form.
# Example:
#

View File

@ -23,8 +23,9 @@ module SimpleForm
map_type :time, :to => :time_select, :options => true
# Collection types
map_type :select, :to => :collection_select, :options => true, :collection => true
map_type :radio, :to => :collection_radio, :collection => true
map_type :select, :to => :collection_select, :options => true, :collection => true
map_type :radio, :to => :collection_radio, :options => true, :collection => true
map_type :check_boxes, :to => :collection_check_box, :options => true, :collection => true
# With priority zones
map_type :country, :to => :country_select, :options => true, :with_priority => true

View File

@ -125,7 +125,7 @@ module SimpleForm
when :has_one
raise ":has_one association are not supported by f.association"
else
attribute = :"#{@reflection.name}_ids"
attribute = :"#{@reflection.name.to_s.singularize}_ids"
if options[:as] == :select
html_options = options[:input_html] ||= {}

View File

@ -1,16 +1,14 @@
require 'test_helper'
class BuilderTest < ActionView::TestCase
# COLLECTION RADIO
test 'collection radio accepts a collection and generate inputs from value method' do
form_for @user do |f|
concat f.collection_radio :active, [true, false], :to_s, :to_s
end
assert_select 'form input[type=radio][value=true]#user_active_true'
assert_select 'form label.collection_radio[for=user_active_true]', 'true'
assert_select 'form input[type=radio][value=false]#user_active_false'
assert_select 'form label.collection_radio[for=user_active_false]', 'false'
end
test 'collection radio accepts a collection and generate inputs from label method' do
@ -18,19 +16,126 @@ class BuilderTest < ActionView::TestCase
concat f.collection_radio :active, [true, false], :to_s, :to_s
end
assert_select 'form label[for=user_active_true]', 'true'
assert_select 'form label[for=user_active_false]', 'false'
assert_select 'form label.collection_radio[for=user_active_true]', 'true'
assert_select 'form label.collection_radio[for=user_active_false]', 'false'
end
test 'collection radio accepts checked item' do
form_for @user do |f|
concat f.collection_radio :active, [[1, true], [0, false]], :last, :first, :checked => true
end
assert_select 'form input[type=radio][value=true][checked=checked]'
assert_no_select 'form input[type=radio][value=false][checked=checked]'
end
test 'collection radio accepts multiple disabled items' do
collection = [[1, true], [0, false], [2, 'other']]
form_for @user do |f|
concat f.collection_radio :active, collection, :last, :first, :disabled => [true, false]
end
assert_select 'form input[type=radio][value=true][disabled=disabled]'
assert_select 'form input[type=radio][value=false][disabled=disabled]'
assert_no_select 'form input[type=radio][value=other][disabled=disabled]'
end
test 'collection radio accepts single disable item' do
collection = [[1, true], [0, false]]
form_for @user do |f|
concat f.collection_radio :active, collection, :last, :first, :disabled => true
end
assert_select 'form input[type=radio][value=true][disabled=disabled]'
assert_no_select 'form input[type=radio][value=false][disabled=disabled]'
end
test 'collection radio accepts html options as input' do
form_for @user do |f|
concat f.collection_radio :active, [[1, true], [0, false]], :last, :first, :class => 'radio'
concat f.collection_radio :active, [[1, true], [0, false]], :last, :first, {}, :class => 'radio'
end
assert_select 'form input[type=radio][value=true].radio#user_active_true'
assert_select 'form input[type=radio][value=false].radio#user_active_false'
end
# COLLECTION CHECK BOX
test 'collection check box accepts a collection and generate a serie of checkboxes for value method' do
collection = [Tag.new(1, 'Tag 1'), Tag.new(2, 'Tag 2')]
form_for @user do |f|
concat f.collection_check_box :tag_ids, collection, :id, :name
end
assert_select "form input[type=hidden][name='user[tag_ids][]'][value=]"
assert_select 'form input#user_tag_ids_1[type=checkbox][value=1]'
assert_select 'form input#user_tag_ids_2[type=checkbox][value=2]'
end
test 'collection check box accepts a collection and generate a serie of checkboxes with labels for label method' do
collection = [Tag.new(1, 'Tag 1'), Tag.new(2, 'Tag 2')]
form_for @user do |f|
concat f.collection_check_box :tag_ids, collection, :id, :name
end
assert_select 'form label.collection_check_box[for=user_tag_ids_1]', 'Tag 1'
assert_select 'form label.collection_check_box[for=user_tag_ids_2]', 'Tag 2'
end
test 'collection check box accepts selected values as :checked option' do
collection = (1..3).map{|i| [i, "Tag #{i}"] }
form_for @user do |f|
concat f.collection_check_box :tag_ids, collection, :first, :last, :checked => [1, 3]
end
assert_select 'form input[type=checkbox][value=1][checked=checked]'
assert_select 'form input[type=checkbox][value=3][checked=checked]'
assert_no_select 'form input[type=checkbox][value=2][checked=checked]'
end
test 'collection check box accepts a single checked value' do
collection = (1..3).map{|i| [i, "Tag #{i}"] }
form_for @user do |f|
concat f.collection_check_box :tag_ids, collection, :first, :last, :checked => 3
end
assert_select 'form input[type=checkbox][value=3][checked=checked]'
assert_no_select 'form input[type=checkbox][value=1][checked=checked]'
assert_no_select 'form input[type=checkbox][value=2][checked=checked]'
end
test 'collection check box accepts multiple disabled items' do
collection = (1..3).map{|i| [i, "Tag #{i}"] }
form_for @user do |f|
concat f.collection_check_box :tag_ids, collection, :first, :last, :disabled => [1, 3]
end
assert_select 'form input[type=checkbox][value=1][disabled=disabled]'
assert_select 'form input[type=checkbox][value=3][disabled=disabled]'
assert_no_select 'form input[type=checkbox][value=2][disabled=disabled]'
end
test 'collection check box accepts single disable item' do
collection = (1..3).map{|i| [i, "Tag #{i}"] }
form_for @user do |f|
concat f.collection_check_box :tag_ids, collection, :first, :last, :disabled => 1
end
assert_select 'form input[type=checkbox][value=1][disabled=disabled]'
assert_no_select 'form input[type=checkbox][value=3][disabled=disabled]'
assert_no_select 'form input[type=checkbox][value=2][disabled=disabled]'
end
test 'collection check box accepts html options' do
collection = [[1, 'Tag 1'], [2, 'Tag 2']]
form_for @user do |f|
concat f.collection_check_box :tag_ids, collection, :first, :last, {}, :class => 'check'
end
assert_select 'form input.check[type=checkbox][value=1]'
assert_select 'form input.check[type=checkbox][value=2]'
end
# SIMPLE FIELDS
test 'simple fields for is available and yields an instance of FormBuilder' do
form_for @user do |f|
f.simple_fields_for :posts do |posts_form|

View File

@ -422,7 +422,7 @@ class FormBuilderTest < ActionView::TestCase
test 'builder creates a select with multiple options for collection associations' do
with_association_for @user, :tags
assert_select 'form select.select#user_tags_ids'
assert_select 'form select.select#user_tag_ids'
assert_select 'form select[multiple=multiple][size=5]'
assert_select 'form select option[value=1]', 'Tag 1'
assert_select 'form select option[value=2]', 'Tag 2'
@ -435,10 +435,26 @@ class FormBuilderTest < ActionView::TestCase
end
test 'builder marks all selected records which already belongs to user' do
@user.tags_ids = [1, 2]
@user.tag_ids = [1, 2]
with_association_for @user, :tags
assert_select 'form select option[value=1][selected=selected]'
assert_select 'form select option[value=2][selected=selected]'
assert_no_select 'form select option[value=3][selected=selected]'
end
test 'builder allows a collection of check boxes for collection associations' do
@user.tag_ids = [1, 2]
with_association_for @user, :tags, :as => :check_boxes
assert_select 'form input#user_tag_ids_1[type=checkbox]'
assert_select 'form input#user_tag_ids_2[type=checkbox]'
assert_select 'form input#user_tag_ids_3[type=checkbox]'
end
test 'builder marks all selected records for collection boxes' do
@user.tag_ids = [1, 2]
with_association_for @user, :tags, :as => :check_boxes
assert_select 'form input[type=checkbox][value=1][checked=checked]'
assert_select 'form input[type=checkbox][value=2][checked=checked]'
assert_no_select 'form input[type=checkbox][value=3][checked=checked]'
end
end