Skip to content

Commit

Permalink
Introduce grouped_collection_select helper.
Browse files Browse the repository at this point in the history
[#1249 state:committed]

Signed-off-by: Jeremy Kemper <jeremy@bitsweat.net>
  • Loading branch information
codeape authored and jeremy committed Aug 10, 2009
1 parent 7d16e94 commit 8c32248
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 0 deletions.
2 changes: 2 additions & 0 deletions 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]
Expand Down
67 changes: 67 additions & 0 deletions actionpack/lib/action_view/helpers/form_options_helper.rb
Expand Up @@ -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

This comment has been minimized.

Copy link
@dam5s

dam5s Aug 14, 2009

I think this should be name option_value_method

# +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

This comment has been minimized.

Copy link
@dam5s

dam5s Aug 14, 2009

I think this should be named option_name_method

# +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.
#
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand Down
34 changes: 34 additions & 0 deletions actionpack/test/template/form_options_helper_test.rb
Expand Up @@ -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
Expand Down

1 comment on commit 8c32248

@iain
Copy link
Contributor

@iain iain commented on 8c32248 Aug 10, 2009

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cool! thanks!

Please sign in to comment.