From e2118db6947dff3646e78d7f481cfdd191f55d4f Mon Sep 17 00:00:00 2001 From: Matt Jones Date: Mon, 16 Feb 2009 02:46:12 -0500 Subject: [PATCH] convert nested arrays in options_for_select to optgroups --- .../lib/action_view/helpers/form_options_helper.rb | 23 ++++++++++++++----- .../test/template/form_options_helper_test.rb | 9 +++++++ 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/actionpack/lib/action_view/helpers/form_options_helper.rb b/actionpack/lib/action_view/helpers/form_options_helper.rb index 6b385ef..5a97148 100644 --- a/actionpack/lib/action_view/helpers/form_options_helper.rb +++ b/actionpack/lib/action_view/helpers/form_options_helper.rb @@ -215,6 +215,13 @@ module ActionView # options_for_select([ "VISA", "MasterCard", "Discover" ], ["VISA", "Discover"]) # \n\n # + # If the "last" of an element is an array, the element will become an optgroup tag, labelled with the + # corresponding "first". Groups can be mixed with single options. + # + # Example: + # options_for_select([ ["First Group", [["Option 1", 1], ["Option 2", 2]]], ["Bare Option", 3] ]) + # \n\n + # # If you wish to specify disabled option tags, set +selected+ to be a hash, with :disabled being either a value # or array of values to be disabled. In this case, you can use :selected to specify selected option tags. # @@ -229,15 +236,19 @@ module ActionView # \n\n\n # # NOTE: Only the option tags are returned, you have to wrap this call in a regular HTML select tag. - def options_for_select(container, selected = nil) + def options_for_select(container, _selected = nil) container = container.to_a if Hash === container - selected, disabled = extract_selected_and_disabled(selected) + selected, disabled = extract_selected_and_disabled(_selected) options_for_select = container.inject([]) do |options, element| - text, value = option_text_and_value(element) - selected_attribute = ' selected="selected"' if option_value_selected?(value, selected) - disabled_attribute = ' disabled="disabled"' if disabled && option_value_selected?(value, disabled) - options << %() + if element.respond_to?(:last) && (element.last.is_a?(Array) || element.last.is_a?(Hash)) + options << content_tag(:optgroup, options_for_select(element.last, _selected), :label => element.first) + else + text, value = option_text_and_value(element) + selected_attribute = ' selected="selected"' if option_value_selected?(value, selected) + disabled_attribute = ' disabled="disabled"' if disabled && option_value_selected?(value, disabled) + options << %() + end end options_for_select.join("\n") diff --git a/actionpack/test/template/form_options_helper_test.rb b/actionpack/test/template/form_options_helper_test.rb index 78db879..505e13d 100644 --- a/actionpack/test/template/form_options_helper_test.rb +++ b/actionpack/test/template/form_options_helper_test.rb @@ -152,6 +152,15 @@ class FormOptionsHelperTest < ActionView::TestCase ) end + def test_nested_array_options_for_select + assert_dom_equal( + "\n\n\n\n", + options_for_select([["Lone Option", "lone"], + ["Group", [["Group Option 1", 1], ["Group Option 2", 2], ["Group Option 3", 3]]], + ["Last Option", "last"]], :selected => 1, :disabled => 3) + ) + end + def test_ducktyped_options_for_select quack = Struct.new(:first, :last) assert_dom_equal( -- 1.5.3.1