Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Make "select" helper handle nested collections #1722

Merged
merged 1 commit into from

5 participants

@AndrewRadev

The select form helper generates a select tag with options from the given [key, value] pairs. This works only for "flat" collections, but I'd like to have it work with nested ones as well. An example:

@post = Post.new
select("post", "origin", {
  "Africa" => [["South Africa", "sa"], ["Somalia", "so"]],
  "Europe" => [["Denmark", "dk"], ["Ireland", "ie"]],
})

Currently, select uses "Africa" and "Europe" as the content of the option tags, and calls to_s on the arrays for the values. With this pull request, the result would instead be something like this:

<select id="post_origin" name="post[origin]">
  <optgroup label="Africa">
    <option value="sa">South Africa</option>
    <option value="so">Somalia</option>
  </optgroup>
  <optgroup label="Europe">
    <option value="dk">Denmark</option>
    <option value="ie">Ireland</option>
  </optgroup>
</select>

Internally, the choices are simply handed to grouped_options_for_select if the collection is more than one level deep.

@gmile

+1

@sikachu
Collaborator

This looks great. Do you mind merge and rebased your patch against current master so we can merge it in? We'd really like the test case and implementation into a single commit.

Thank you.

@AndrewRadev

I rebased the code against the current master and force-pushed, so it should merge cleanly now. I also squashed the first test case and the first implementation attempt together. Is that okay or should I just clump it all in a single commit? Personally, I'd prefer to keep it as it is right now, since the history might be useful, even if it is just a small patch.

@sikachu
Collaborator

We'd more prefer them to be squashed into single commit. The commit (patch) should coming with test case, documentation, implementation, and guide update (If applicable.) Would you mind squashed them together again.

Thanks a lot. :)

@AndrewRadev AndrewRadev Grouped select helper
FormBuilder#select now works with a nested data structure.
587dd7d
@AndrewRadev

Okay then, I squashed them into a single commit and rebased against master again. Thanks for merging :).

@josevalim josevalim merged commit 1939fa3 into from
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Jul 11, 2011
  1. @AndrewRadev

    Grouped select helper

    AndrewRadev authored
    FormBuilder#select now works with a nested data structure.
This page is out of date. Refresh to see the latest.
View
14 actionpack/lib/action_view/helpers/form_options_helper.rb
@@ -105,7 +105,10 @@ module FormOptionsHelper
# Create a select tag and a series of contained option tags for the provided object and method.
# The option currently held by the object will be selected, provided that the object is available.
- # See options_for_select for the required format of the choices parameter.
+ #
+ # There are two possible formats for the choices parameter, corresponding to other helpers' output:
+ # * A flat collection: see options_for_select
+ # * A nested collection: see grouped_options_for_select
#
# Example with @post.person_id => 1:
# select("post", "person_id", Person.all.collect {|p| [ p.name, p.id ] }, { :include_blank => true })
@@ -575,7 +578,14 @@ class InstanceTag #:nodoc:
def to_select_tag(choices, options, html_options)
selected_value = options.has_key?(:selected) ? options[:selected] : value(object)
- select_content_tag(options_for_select(choices, :selected => selected_value, :disabled => options[:disabled]), options, html_options)
+
+ if !choices.empty? && choices.try(:first).try(:second).respond_to?(:each)
+ option_tags = grouped_options_for_select(choices, :selected => selected_value, :disabled => options[:disabled])
+ else
+ option_tags = options_for_select(choices, :selected => selected_value, :disabled => options[:disabled])
+ end
+
+ select_content_tag(option_tags, options, html_options)
end
def to_collection_select_tag(collection, value_method, text_method, options, html_options)
View
36 actionpack/test/template/form_options_helper_test.rb
@@ -385,6 +385,42 @@ def test_select_without_multiple
)
end
+ def test_select_with_grouped_collection_as_nested_array
+ @post = Post.new
+
+ countries_by_continent = [
+ ["<Africa>", [["<South Africa>", "<sa>"], ["Somalia", "so"]]],
+ ["Europe", [["Denmark", "dk"], ["Ireland", "ie"]]],
+ ]
+
+ assert_dom_equal(
+ [
+ %Q{<select id="post_origin" name="post[origin]"><optgroup label="&lt;Africa&gt;"><option value="&lt;sa&gt;">&lt;South Africa&gt;</option>},
+ %Q{<option value="so">Somalia</option></optgroup><optgroup label="Europe"><option value="dk">Denmark</option>},
+ %Q{<option value="ie">Ireland</option></optgroup></select>},
+ ].join("\n"),
+ select("post", "origin", countries_by_continent)
+ )
+ end
+
+ def test_select_with_grouped_collection_as_hash
+ @post = Post.new
+
+ countries_by_continent = {
+ "<Africa>" => [["<South Africa>", "<sa>"], ["Somalia", "so"]],
+ "Europe" => [["Denmark", "dk"], ["Ireland", "ie"]],
+ }
+
+ assert_dom_equal(
+ [
+ %Q{<select id="post_origin" name="post[origin]"><optgroup label="&lt;Africa&gt;"><option value="&lt;sa&gt;">&lt;South Africa&gt;</option>},
+ %Q{<option value="so">Somalia</option></optgroup><optgroup label="Europe"><option value="dk">Denmark</option>},
+ %Q{<option value="ie">Ireland</option></optgroup></select>},
+ ].join("\n"),
+ select("post", "origin", countries_by_continent)
+ )
+ end
+
def test_select_with_boolean_method
@post = Post.new
@post.allow_comments = false
Something went wrong with that request. Please try again.