diff --git a/lib/simple_form/form_builder.rb b/lib/simple_form/form_builder.rb index 5af1d92f..3eb9f873 100644 --- a/lib/simple_form/form_builder.rb +++ b/lib/simple_form/form_builder.rb @@ -20,6 +20,7 @@ module SimpleForm map_type :integer, :decimal, :float, :to => SimpleForm::Inputs::NumericInput map_type :range, :to => SimpleForm::Inputs::RangeInput map_type :select, :radio, :check_boxes, :to => SimpleForm::Inputs::CollectionInput + map_type :grouped_select, :to => SimpleForm::Inputs::GroupedCollectionInput map_type :date, :time, :datetime, :to => SimpleForm::Inputs::DateTimeInput map_type :country, :time_zone, :to => SimpleForm::Inputs::PriorityInput map_type :boolean, :to => SimpleForm::Inputs::BooleanInput diff --git a/lib/simple_form/inputs.rb b/lib/simple_form/inputs.rb index 40bfc593..0fc116d8 100644 --- a/lib/simple_form/inputs.rb +++ b/lib/simple_form/inputs.rb @@ -1,17 +1,18 @@ module SimpleForm module Inputs - autoload :Base, 'simple_form/inputs/base' - autoload :BlockInput, 'simple_form/inputs/block_input' - autoload :BooleanInput, 'simple_form/inputs/boolean_input' - autoload :CollectionInput, 'simple_form/inputs/collection_input' - autoload :DateTimeInput, 'simple_form/inputs/date_time_input' - autoload :FileInput, 'simple_form/inputs/file_input' - autoload :HiddenInput, 'simple_form/inputs/hidden_input' - autoload :NumericInput, 'simple_form/inputs/numeric_input' - autoload :PasswordInput, 'simple_form/inputs/password_input' - autoload :PriorityInput, 'simple_form/inputs/priority_input' - autoload :RangeInput, 'simple_form/inputs/range_input' - autoload :StringInput, 'simple_form/inputs/string_input' - autoload :TextInput, 'simple_form/inputs/text_input' + autoload :Base, 'simple_form/inputs/base' + autoload :BlockInput, 'simple_form/inputs/block_input' + autoload :BooleanInput, 'simple_form/inputs/boolean_input' + autoload :CollectionInput, 'simple_form/inputs/collection_input' + autoload :GroupedCollectionInput, 'simple_form/inputs/grouped_collection_input' + autoload :DateTimeInput, 'simple_form/inputs/date_time_input' + autoload :FileInput, 'simple_form/inputs/file_input' + autoload :HiddenInput, 'simple_form/inputs/hidden_input' + autoload :NumericInput, 'simple_form/inputs/numeric_input' + autoload :PasswordInput, 'simple_form/inputs/password_input' + autoload :PriorityInput, 'simple_form/inputs/priority_input' + autoload :RangeInput, 'simple_form/inputs/range_input' + autoload :StringInput, 'simple_form/inputs/string_input' + autoload :TextInput, 'simple_form/inputs/text_input' end end diff --git a/lib/simple_form/inputs/collection_input.rb b/lib/simple_form/inputs/collection_input.rb index d1ec9ec6..1e409fa4 100644 --- a/lib/simple_form/inputs/collection_input.rb +++ b/lib/simple_form/inputs/collection_input.rb @@ -65,9 +65,7 @@ module SimpleForm [label, value] end - def detect_common_display_methods - collection_classes = detect_collection_classes - + def detect_common_display_methods(collection_classes = detect_collection_classes) if collection_classes.include?(Array) { :label => :first, :value => :last } elsif collection_includes_basic_objects?(collection_classes) @@ -80,8 +78,8 @@ module SimpleForm end end - def detect_collection_classes - collection.map { |e| e.class }.uniq + def detect_collection_classes(some_collection = collection) + some_collection.map { |e| e.class }.uniq end def collection_includes_basic_objects?(collection_classes) diff --git a/lib/simple_form/inputs/grouped_collection_input.rb b/lib/simple_form/inputs/grouped_collection_input.rb new file mode 100644 index 00000000..392f5990 --- /dev/null +++ b/lib/simple_form/inputs/grouped_collection_input.rb @@ -0,0 +1,38 @@ +module SimpleForm + module Inputs + class GroupedCollectionInput < CollectionInput + def input + label_method, value_method = detect_collection_methods + @builder.grouped_collection_select(attribute_name, group_collection, + group_method, group_label_method, value_method, label_method, + input_options, input_html_options) + end + + private + + def group_collection + @group_collection ||= options.delete(:collection) + end + + # Sample collection + def collection + @collection ||= group_collection.first.try(:send, group_method) + end + + def group_method + @group_method ||= options.delete(:group_method) + end + + def group_label_method + label = options.delete(:group_label_method) + + unless label + common_method_for = detect_common_display_methods( detect_collection_classes(group_collection) ) + label = common_method_for[:label] + end + + label + end + end + end +end diff --git a/test/inputs/grouped_collection_input_test.rb b/test/inputs/grouped_collection_input_test.rb new file mode 100644 index 00000000..18623778 --- /dev/null +++ b/test/inputs/grouped_collection_input_test.rb @@ -0,0 +1,21 @@ +# encoding: UTF-8 +require 'test_helper' + +class GroupedCollectionInputTest < ActionView::TestCase + test 'input should have grouped options' do + with_input_for @user, :name, :grouped_select, + :collection => [['Authors', ['Jose', 'Carlos']], ['General', ['Bob', 'John']]], + :group_method => :last + assert_select 'select.grouped_select#user_name' do + assert_select 'optgroup[label=Authors]' do + assert_select 'option', 'Jose' + assert_select 'option', 'Carlos' + end + + assert_select 'optgroup[label=General]' do + assert_select 'option', 'Bob' + assert_select 'option', 'John' + end + end + end +end