aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--actionpack/lib/action_view/helpers/form_options_helper.rb35
-rw-r--r--actionpack/test/template/form_options_helper_test.rb84
2 files changed, 115 insertions, 4 deletions
diff --git a/actionpack/lib/action_view/helpers/form_options_helper.rb b/actionpack/lib/action_view/helpers/form_options_helper.rb
index 54c82cbd1d..40b9b0d135 100644
--- a/actionpack/lib/action_view/helpers/form_options_helper.rb
+++ b/actionpack/lib/action_view/helpers/form_options_helper.rb
@@ -189,11 +189,13 @@ module ActionView
# 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)
container = container.to_a if Hash === container
+ 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)
- options << %(<option value="#{html_escape(value.to_s)}"#{selected_attribute}>#{html_escape(text.to_s)}</option>)
+ disabled_attribute = ' disabled="disabled"' if disabled && option_value_selected?(value, disabled)
+ options << %(<option value="#{html_escape(value.to_s)}"#{selected_attribute}#{disabled_attribute}>#{html_escape(text.to_s)}</option>)
end
options_for_select.join("\n")
@@ -220,7 +222,12 @@ module ActionView
options = collection.map do |element|
[element.send(text_method), element.send(value_method)]
end
- options_for_select(options, selected)
+ selected, disabled = extract_selected_and_disabled(selected)
+ select_deselect = {}
+ select_deselect[:selected] = extract_values_from_collection(collection, value_method, selected)
+ select_deselect[:disabled] = extract_values_from_collection(collection, value_method, disabled)
+
+ options_for_select(options, select_deselect)
end
# Returns a string of <tt><option></tt> tags, like <tt>options_from_collection_for_select</tt>, but
@@ -388,6 +395,24 @@ module ActionView
value == selected
end
end
+
+ def extract_selected_and_disabled(selected)
+ if selected.is_a?(Hash)
+ [selected[:selected], selected[:disabled]]
+ else
+ [selected, nil]
+ end
+ end
+
+ def extract_values_from_collection(collection, value_method, selected)
+ if selected.is_a?(Proc)
+ collection.map do |element|
+ element.send(value_method) if selected.call(element)
+ end.compact
+ else
+ selected
+ end
+ end
end
class InstanceTag #:nodoc:
@@ -398,16 +423,18 @@ module ActionView
add_default_name_and_id(html_options)
value = value(object)
selected_value = options.has_key?(:selected) ? options[:selected] : value
- content_tag("select", add_options(options_for_select(choices, selected_value), options, selected_value), html_options)
+ disabled_value = options.has_key?(:disabled) ? options[:disabled] : nil
+ content_tag("select", add_options(options_for_select(choices, :selected => selected_value, :disabled => disabled_value), options, selected_value), html_options)
end
def to_collection_select_tag(collection, value_method, text_method, options, html_options)
html_options = html_options.stringify_keys
add_default_name_and_id(html_options)
value = value(object)
+ disabled_value = options.has_key?(:disabled) ? options[:disabled] : nil
selected_value = options.has_key?(:selected) ? options[:selected] : value
content_tag(
- "select", add_options(options_from_collection_for_select(collection, value_method, text_method, selected_value), options, value), html_options
+ "select", add_options(options_from_collection_for_select(collection, value_method, text_method, :selected => selected_value, :disabled => disabled_value), options, value), html_options
)
end
diff --git a/actionpack/test/template/form_options_helper_test.rb b/actionpack/test/template/form_options_helper_test.rb
index 2dbd2ecdd4..78db87971b 100644
--- a/actionpack/test/template/form_options_helper_test.rb
+++ b/actionpack/test/template/form_options_helper_test.rb
@@ -45,6 +45,41 @@ class FormOptionsHelperTest < ActionView::TestCase
)
end
+ def test_collection_options_with_proc_for_selected
+ assert_dom_equal(
+ "<option value=\"&lt;Abe&gt;\">&lt;Abe&gt; went home</option>\n<option value=\"Babe\" selected=\"selected\">Babe went home</option>\n<option value=\"Cabe\">Cabe went home</option>",
+ options_from_collection_for_select(dummy_posts, "author_name", "title", lambda{|p| p.author_name == 'Babe' })
+ )
+ end
+
+ def test_collection_options_with_disabled_value
+ assert_dom_equal(
+ "<option value=\"&lt;Abe&gt;\">&lt;Abe&gt; went home</option>\n<option value=\"Babe\" disabled=\"disabled\">Babe went home</option>\n<option value=\"Cabe\">Cabe went home</option>",
+ options_from_collection_for_select(dummy_posts, "author_name", "title", :disabled => "Babe")
+ )
+ end
+
+ def test_collection_options_with_disabled_array
+ assert_dom_equal(
+ "<option value=\"&lt;Abe&gt;\">&lt;Abe&gt; went home</option>\n<option value=\"Babe\" disabled=\"disabled\">Babe went home</option>\n<option value=\"Cabe\" disabled=\"disabled\">Cabe went home</option>",
+ options_from_collection_for_select(dummy_posts, "author_name", "title", :disabled => [ "Babe", "Cabe" ])
+ )
+ end
+
+ def test_collection_options_with_preselected_and_disabled_value
+ assert_dom_equal(
+ "<option value=\"&lt;Abe&gt;\">&lt;Abe&gt; went home</option>\n<option value=\"Babe\" disabled=\"disabled\">Babe went home</option>\n<option value=\"Cabe\" selected=\"selected\">Cabe went home</option>",
+ options_from_collection_for_select(dummy_posts, "author_name", "title", :selected => "Cabe", :disabled => "Babe")
+ )
+ end
+
+ def test_collection_options_with_proc_for_disabled
+ assert_dom_equal(
+ "<option value=\"&lt;Abe&gt;\">&lt;Abe&gt; went home</option>\n<option value=\"Babe\" disabled=\"disabled\">Babe went home</option>\n<option value=\"Cabe\" disabled=\"disabled\">Cabe went home</option>",
+ options_from_collection_for_select(dummy_posts, "author_name", "title", :disabled => lambda{|p| %w(Babe Cabe).include? p.author_name })
+ )
+ end
+
def test_array_options_for_select
assert_dom_equal(
"<option value=\"&lt;Denmark&gt;\">&lt;Denmark&gt;</option>\n<option value=\"USA\">USA</option>\n<option value=\"Sweden\">Sweden</option>",
@@ -66,6 +101,27 @@ class FormOptionsHelperTest < ActionView::TestCase
)
end
+ def test_array_options_for_select_with_disabled_value
+ assert_dom_equal(
+ "<option value=\"Denmark\">Denmark</option>\n<option value=\"&lt;USA&gt;\" disabled=\"disabled\">&lt;USA&gt;</option>\n<option value=\"Sweden\">Sweden</option>",
+ options_for_select([ "Denmark", "<USA>", "Sweden" ], :disabled => "<USA>")
+ )
+ end
+
+ def test_array_options_for_select_with_disabled_array
+ assert_dom_equal(
+ "<option value=\"Denmark\">Denmark</option>\n<option value=\"&lt;USA&gt;\" disabled=\"disabled\">&lt;USA&gt;</option>\n<option value=\"Sweden\" disabled=\"disabled\">Sweden</option>",
+ options_for_select([ "Denmark", "<USA>", "Sweden" ], :disabled => ["<USA>", "Sweden"])
+ )
+ end
+
+ def test_array_options_for_select_with_selection_and_disabled_value
+ assert_dom_equal(
+ "<option value=\"Denmark\" selected=\"selected\">Denmark</option>\n<option value=\"&lt;USA&gt;\" disabled=\"disabled\">&lt;USA&gt;</option>\n<option value=\"Sweden\">Sweden</option>",
+ options_for_select([ "Denmark", "<USA>", "Sweden" ], :selected => "Denmark", :disabled => "<USA>")
+ )
+ end
+
def test_array_options_for_string_include_in_other_string_bug_fix
assert_dom_equal(
"<option value=\"ruby\">ruby</option>\n<option value=\"rubyonrails\" selected=\"selected\">rubyonrails</option>",
@@ -352,6 +408,24 @@ class FormOptionsHelperTest < ActionView::TestCase
)
end
+ def test_select_with_disabled_value
+ @post = Post.new
+ @post.category = "<mus>"
+ assert_dom_equal(
+ "<select id=\"post_category\" name=\"post[category]\"><option value=\"abe\">abe</option>\n<option value=\"&lt;mus&gt;\" selected=\"selected\">&lt;mus&gt;</option>\n<option value=\"hest\" disabled=\"disabled\">hest</option></select>",
+ select("post", "category", %w( abe <mus> hest ), :disabled => 'hest')
+ )
+ end
+
+ def test_select_with_disabled_array
+ @post = Post.new
+ @post.category = "<mus>"
+ assert_dom_equal(
+ "<select id=\"post_category\" name=\"post[category]\"><option value=\"abe\" disabled=\"disabled\">abe</option>\n<option value=\"&lt;mus&gt;\" selected=\"selected\">&lt;mus&gt;</option>\n<option value=\"hest\" disabled=\"disabled\">hest</option></select>",
+ select("post", "category", %w( abe <mus> hest ), :disabled => ['hest', 'abe'])
+ )
+ end
+
def test_collection_select
@post = Post.new
@post.author_name = "Babe"
@@ -448,6 +522,16 @@ class FormOptionsHelperTest < ActionView::TestCase
)
end
+ def test_collection_select_with_disabled
+ @post = Post.new
+ @post.author_name = "Babe"
+
+ assert_dom_equal(
+ "<select id=\"post_author_name\" name=\"post[author_name]\"><option value=\"&lt;Abe&gt;\">&lt;Abe&gt;</option>\n<option value=\"Babe\" selected=\"selected\">Babe</option>\n<option value=\"Cabe\" disabled=\"disabled\">Cabe</option></select>",
+ collection_select("post", "author_name", dummy_posts, "author_name", "author_name", :disabled => 'Cabe')
+ )
+ end
+
def test_time_zone_select
@firm = Firm.new("D")
html = time_zone_select( "firm", "time_zone" )