Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Introduce grouped_collection_select helper.

[#1249 state:committed]

Signed-off-by: Jeremy Kemper <jeremy@bitsweat.net>
  • Loading branch information...
commit 8c32248acbd71f7906a037fad499e2f8cae61bed 1 parent 7d16e94
codeape authored jeremy committed
View
2  actionpack/CHANGELOG
@@ -1,5 +1,7 @@
*Edge*
+* Introduce grouped_collection_select helper. #1249 [Dan Codeape, Erik Ostrom]
+
* Make sure javascript_include_tag/stylesheet_link_tag does not append ".js" or ".css" onto external urls. #1664 [Matthew Rudy Jacobs]
* Ruby 1.9: fix Content-Length for multibyte send_data streaming. #2661 [Sava Chankov]
View
67 actionpack/lib/action_view/helpers/form_options_helper.rb
@@ -162,6 +162,60 @@ def collection_select(object, method, collection, value_method, text_method, opt
InstanceTag.new(object, method, self, options.delete(:object)).to_collection_select_tag(collection, value_method, text_method, options, html_options)
end
+
+ # Returns <tt><select></tt>, <tt><optgroup></tt> and <tt><option></tt> tags for the collection of existing return values of
+ # +method+ for +object+'s class. The value returned from calling +method+ on the instance +object+ will
+ # be selected. If calling +method+ returns +nil+, no selection is made without including <tt>:prompt</tt>
+ # or <tt>:include_blank</tt> in the +options+ hash.
+ #
+ # Parameters:
+ # * +object+ - The instance of the class to be used for the select tag
+ # * +method+ - The attribute of +object+ corresponding to the select tag
+ # * +collection+ - An array of objects representing the <tt><optgroup></tt> tags.
+ # * +group_method+ - The name of a method which, when called on a member of +collection+, returns an
+ # array of child objects representing the <tt><option></tt> tags.
+ # * +group_label_method+ - The name of a method which, when called on a member of +collection+, returns a
+ # string to be used as the +label+ attribute for its <tt><optgroup></tt> tag.
+ # * +option_key_method+ - The name of a method which, when called on a child object of a member of
@dam5s
dam5s added a note

I think this should be name option_value_method

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+ # +collection+, returns a value to be used as the +value+ attribute for its <tt><option></tt> tag.
+ # * +option_value_method+ - The name of a method which, when called on a child object of a member of
@dam5s
dam5s added a note

I think this should be named option_name_method

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+ # +collection+, returns a value to be used as the contents of its <tt><option></tt> tag.
+ #
+ # Example object structure for use with this method:
+ # class Continent < ActiveRecord::Base
+ # has_many :countries
+ # # attribs: id, name
+ # end
+ # class Country < ActiveRecord::Base
+ # belongs_to :continent
+ # # attribs: id, name, continent_id
+ # end
+ # class City < ActiveRecord::Base
+ # belongs_to :country
+ # # attribs: id, name, country_id
+ # end
+ #
+ # Sample usage:
+ # grouped_collection_select(:city, :country_id, @continents, :countries, :name, :id, :name)
+ #
+ # Possible output:
+ # <select name="city[country_id]">
+ # <optgroup label="Africa">
+ # <option value="1">South Africa</option>
+ # <option value="3">Somalia</option>
+ # </optgroup>
+ # <optgroup label="Europe">
+ # <option value="7" selected="selected">Denmark</option>
+ # <option value="2">Ireland</option>
+ # </optgroup>
+ # </select>
+ #
+ def grouped_collection_select(object, method, collection, group_method, group_label_method, option_key_method, option_value_method, options = {}, html_options = {})
+ InstanceTag.new(object, method, self, options.delete(:object)).to_grouped_collection_select_tag(collection, group_method, group_label_method, option_key_method, option_value_method, options, html_options)
+ end
+
+
+
# Return select and option tags for the given object and method, using
# #time_zone_options_for_select to generate the list of option tags.
#
@@ -490,6 +544,15 @@ def to_collection_select_tag(collection, value_method, text_method, options, htm
)
end
+ def to_grouped_collection_select_tag(collection, group_method, group_label_method, option_key_method, option_value_method, options, html_options)
+ html_options = html_options.stringify_keys
+ add_default_name_and_id(html_options)
+ value = value(object)
+ content_tag(
+ "select", add_options(option_groups_from_collection_for_select(collection, group_method, group_label_method, option_key_method, option_value_method, value), options, value), html_options
+ )
+ end
+
def to_time_zone_select_tag(priority_zones, options, html_options)
html_options = html_options.stringify_keys
add_default_name_and_id(html_options)
@@ -524,6 +587,10 @@ def collection_select(method, collection, value_method, text_method, options = {
@template.collection_select(@object_name, method, collection, value_method, text_method, objectify_options(options), @default_options.merge(html_options))
end
+ def grouped_collection_select(method, collection, group_method, group_label_method, option_key_method, option_value_method, options = {}, html_options = {})
+ @template.grouped_collection_select(@object_name, method, collection, group_method, group_label_method, option_key_method, option_value_method, objectify_options(options), @default_options.merge(html_options))
+ end
+
def time_zone_select(method, priority_zones = nil, options = {}, html_options = {})
@template.time_zone_select(@object_name, method, priority_zones, objectify_options(options), @default_options.merge(html_options))
end
View
34 actionpack/test/template/form_options_helper_test.rb
@@ -763,6 +763,40 @@ def test_time_zone_select_with_default_time_zone_and_value
html
end
+ def test_grouped_collection_select
+ @continents = [
+ Continent.new("<Africa>", [Country.new("<sa>", "<South Africa>"), Country.new("so", "Somalia")] ),
+ Continent.new("Europe", [Country.new("dk", "Denmark"), Country.new("ie", "Ireland")] )
+ ]
+
+ @post = Post.new
+ @post.origin = 'dk'
+
+ 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>\n<option value="so">Somalia</option></optgroup><optgroup label="Europe"><option value="dk" selected="selected">Denmark</option>\n<option value="ie">Ireland</option></optgroup></select>},
+ grouped_collection_select("post", "origin", @continents, :countries, :continent_name, :country_id, :country_name)
+ )
+ end
+
+ def test_grouped_collection_select_under_fields_for
+ @continents = [
+ Continent.new("<Africa>", [Country.new("<sa>", "<South Africa>"), Country.new("so", "Somalia")] ),
+ Continent.new("Europe", [Country.new("dk", "Denmark"), Country.new("ie", "Ireland")] )
+ ]
+
+ @post = Post.new
+ @post.origin = 'dk'
+
+ fields_for :post, @post do |f|
+ concat f.grouped_collection_select("origin", @continents, :countries, :continent_name, :country_id, :country_name)
+ end
+
+ 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>\n<option value="so">Somalia</option></optgroup><optgroup label="Europe"><option value="dk" selected="selected">Denmark</option>\n<option value="ie">Ireland</option></optgroup></select>},
+ output_buffer
+ )
+ end
+
private
def dummy_posts

1 comment on commit 8c32248

@iain

cool! thanks!

Please sign in to comment.
Something went wrong with that request. Please try again.