Permalink
Browse files

Adjusting select_input and radio_input so they both allow the collect…

…ion to be passed in as either an Array of Strings (e.g [ 'General', 'Design', 'Development' ]) or a Hash of Strings (e.g { 'General' => 'gen', 'Design' => 'des', 'Development' => 'dev' }).

Signed-off-by: Justin French <justin@indent.com.au>
  • Loading branch information...
1 parent fce54c2 commit 5be606127cbcd2fb7386010a21e1390ed251e501 @andypearson andypearson committed with Feb 22, 2009
Showing with 95 additions and 9 deletions.
  1. +20 −8 lib/formtastic.rb
  2. +75 −1 spec/formtastic_spec.rb
View
28 lib/formtastic.rb
@@ -345,13 +345,21 @@ def method_required?(attribute, required_option) #:nodoc:
# f.input :author_id, :as => :select, :value_method => :value
def select_input(method, options)
options[:collection] ||= find_parent_objects_for_column(method)
- options[:label_method] ||= @@collection_label_methods.detect { |m| options[:collection].first.respond_to?(m) }
+ options[:label_method] ||= detect_label_method(options[:collection])
options[:value_method] ||= :id
- choices = options[:collection].map { |o| [o.send(options[:label_method]), o.send(options[:value_method])] }
+ choices = formatted_collection(options[:collection], options[:label_method], options[:value_method])
input_label(method, options) + template.select(@object_name, method, choices, set_options(options))
end
-
+
+ def detect_label_method(collection) #:nodoc:
+ (!collection.instance_of?(Hash)) ? @@collection_label_methods.detect { |m| collection.first.respond_to?(m) } : nil
+ end
+
+ def formatted_collection(collection, label_method, value_method = :id) #:nodoc:
+ return collection if (collection.instance_of?(Hash) || (collection.instance_of?(Array) && collection.first.instance_of?(String)))
+ collection.map { |o| [o.send(label_method), o.send(value_method)] }
+ end
# Outputs a fieldset containing a legend for the label text, and an ordered list (ol) of list
# items, one for each possible choice in the belongs_to association. Each li contains a
@@ -399,16 +407,20 @@ def select_input(method, options)
# f.input :author_id, :as => :radio, :label_method => :label
def radio_input(method, options)
options[:collection] ||= find_parent_objects_for_column(method)
- options[:label_method] ||= @@collection_label_methods.detect { |m| options[:collection].first.respond_to?(m) }
-
+ options[:label_method] ||= detect_label_method(options[:collection])
+
+ choices = formatted_collection(options[:collection], options[:label_method])
template.content_tag(:fieldset,
%{<legend><span>#{label_text(method, options)}</span></legend>} +
template.content_tag(:ol,
- options[:collection].map { |c|
+ choices.map { |c|
+ label = (!c.instance_of?(String)) ? c.first : c
+ value = (!c.instance_of?(String)) ? c.last : c
+
template.content_tag(:li,
template.content_tag(:label,
- "#{template.radio_button(@object_name, method, c.id, set_options(options))} #{c.send(options[:label_method])}",
- :for => "#{@object_name}_#{method}_#{c.id}"
+ "#{template.radio_button(@object_name, method, value, set_options(options))} #{label}",
+ :for => "#{@object_name}_#{method}_#{value}".downcase
)
)
}
View
76 spec/formtastic_spec.rb
@@ -888,7 +888,45 @@ def custom(arg1, arg2, options = {})
end
output_buffer.should have_tag('form li fieldset ol li', :count => @authors.size)
end
-
+
+ describe 'and the :collection is an array of strings' do
+
+ before do
+ @new_post.stub!(:category_name).and_return('')
+ @categories = [ 'General', 'Design', 'Development' ]
+ end
+
+ it 'should use the string as the label text and value for each radio button' do
+ semantic_form_for(@new_post) do |builder|
+ concat(builder.input(:category_name, :as => :radio, :collection => @categories))
+ end
+ @categories.each do |item|
+ output_buffer.should have_tag('form li fieldset ol li label', /#{item}/i)
+ output_buffer.should have_tag('form li fieldset ol li label input[@value='+item+']')
+ end
+ end
+
+ end
+
+ describe 'and the :collection is a hash of strings' do
+
+ before do
+ @new_post.stub!(:category_name).and_return('')
+ @categories = { 'General' => 'gen', 'Design' => 'des','Development' => 'dev' }
+ end
+
+ it 'should use the key as the label text and the hash value as the value attribute for each radio button' do
+ semantic_form_for(@new_post) do |builder|
+ concat(builder.input(:category_name, :as => :radio, :collection => @categories))
+ end
+ @categories.each do |label, value|
+ output_buffer.should have_tag('form li fieldset ol li label', /#{label}/i)
+ output_buffer.should have_tag('form li fieldset ol li label input[@value='+value+']')
+ end
+ end
+
+ end
+
end
describe 'when the :label_method option is provided' do
@@ -993,6 +1031,42 @@ def custom(arg1, arg2, options = {})
end
output_buffer.should have_tag('form li select option', :count => @authors.size)
end
+
+ describe 'and the :collection is an array of strings' do
+
+ before do
+ @new_post.stub!(:category_name).and_return('')
+ @categories = [ 'General', 'Design', 'Development' ]
+ end
+
+ it 'should use the string as the text and value for each option element' do
+ semantic_form_for(@new_post) do |builder|
+ concat(builder.input(:category_name, :as => :select, :collection => @categories))
+ end
+ @categories.each do |item|
+ output_buffer.should have_tag('form li select option[@value='+item+']', item)
+ end
+ end
+
+ end
+
+ describe 'and the :collection is a hash of strings' do
+
+ before do
+ @new_post.stub!(:category_name).and_return('')
+ @categories = { 'General' => 'gen', 'Design' => 'des','Development' => 'dev' }
+ end
+
+ it 'should use the key as the text and the hash value as the value attribute for each option element' do
+ semantic_form_for(@new_post) do |builder|
+ concat(builder.input(:category_name, :as => :select, :collection => @categories))
+ end
+ @categories.each do |label, value|
+ output_buffer.should have_tag('form li select option[@value='+value+']', label)
+ end
+ end
+
+ end
end

1 comment on commit 5be6061

@andypearson

Thanks for the pull Justin! Hopefully this will come in handy for more people than just me.

Please sign in to comment.