Browse files

Add Formtastic::SemanticFormBuilder.collection_label_methods to allow…

… for a list

of possible label text methods. Creating a #to_label method in the model layer
feels like it crosses a boundary by putting view logic in the model layer. With
that in mind, having to set :label_method every time it's needed was cumbersome.

Signed-off-by: Justin French <justin@indent.com.au>
  • Loading branch information...
1 parent 282b28c commit 30cfc86214e1fc42c0735e62ece8055d1821ebf8 @sprsquish sprsquish committed with Feb 16, 2009
Showing with 43 additions and 63 deletions.
  1. +10 −0 README.textile
  2. +9 −9 lib/formtastic.rb
  3. +24 −54 spec/formtastic_spec.rb
View
10 README.textile
@@ -98,6 +98,16 @@ If you wish, put something like this in config/initializers/formtastic_config.rb
# Set the method called on label text to determine its format (:titleize, :humanize, :to_s, etc)
Formtastic::SemanticFormBuilder.label_str_method = :titleize
+
+ # Set the possible methods to be called for label text
+ # Whichever method is found first on the object will be used to set the text of the label for that object
+ # So in the following object:
+ # class User
+ # def full_name; end
+ # def title; end
+ # end
+ # The #full_name method will determine what shows up in the label
+ Formtastic::SemanticFormBuilder.collection_label_methods = %w[to_label display_name full_name name title username login value to_s]
</pre>
View
18 lib/formtastic.rb
@@ -23,8 +23,9 @@ class SemanticFormBuilder < ActionView::Helpers::FormBuilder
@@optional_string = ''
@@inline_errors = :sentence
@@label_str_method = :titleize
+ @@collection_label_methods = %w[to_label display_name full_name name title username login value to_s]
- cattr_accessor :all_fields_required_by_default, :required_string, :optional_string, :inline_errors, :label_str_method
+ cattr_accessor :all_fields_required_by_default, :required_string, :optional_string, :inline_errors, :label_str_method, :collection_label_methods
attr_accessor :template
@@ -319,14 +320,12 @@ def method_required?(attribute, required_option) #:nodoc:
# f.input :author_id, :as => :select, :collection => Author.find(:all)
# f.input :author_id, :as => :select, :collection => [@justin, @kate]
#
- # Note: This input calls #to_label on each record in the parent association, so in the example
- # where a Post belongs_to an Author, you need to define an instance method to_label on Post,
- # which will be used as the text for the each option in the select. You can specify an
- # alternate method with the :label_method option:
+ # Note: This input looks for a label method in the parent association.
#
# You can customize the text label inside each option tag, by naming the correct method
# (:full_name, :display_name, :account_number, etc) to call on each object in the collection
- # by passing in the :label_method option. By default the :label_method is :to_label.
+ # by passing in the :label_method option. By default the :label_method is whichever element of
+ # Formtastic::SemanticFormBuilder.collection_label_methods is found first.
#
# Examples:
#
@@ -346,7 +345,7 @@ 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] ||= options[:collection].first.respond_to?(:to_label) ? :to_label : :to_s
+ options[:label_method] ||= @@collection_label_methods.detect { |m| options[:collection].first.respond_to?(m) }
options[:value_method] ||= :id
choices = options[:collection].map { |o| [o.send(options[:label_method]), o.send(options[:value_method])] }
@@ -389,7 +388,8 @@ def select_input(method, options)
#
# You can also customize the text label inside each option tag, by naming the correct method
# (:full_name, :display_name, :account_number, etc) to call on each object in the collection
- # by passing in the :label_method option. By default the :label_method is :to_label.
+ # by passing in the :label_method option. By default the :label_method is whichever element of
+ # Formtastic::SemanticFormBuilder.collection_label_methods is found first.
#
# Examples:
#
@@ -399,7 +399,7 @@ 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] ||= options[:collection].first.respond_to?(:to_label) ? :to_label : :to_s
+ options[:label_method] ||= @@collection_label_methods.detect { |m| options[:collection].first.respond_to?(m) }
template.content_tag(:fieldset,
%{<legend><span>#{label_text(method, options)}</span></legend>} +
View
78 spec/formtastic_spec.rb
@@ -878,37 +878,23 @@ def custom(arg1, arg2, options = {})
end
describe 'when the :label_method option is not provided' do
-
- describe 'when the collection objects repond to :to_label' do
- before do
- @fred.stub!(:respond_to?).with(:to_label).and_return(true)
- semantic_form_for(@new_post) do |builder|
- concat(builder.input(:author_id, :as => :radio))
- end
- end
-
- it 'should render the options with :to_s as the label' do
- Author.find(:all).each do |author|
- output_buffer.should have_tag("form li fieldset ol li label", /#{Regexp.escape(author.to_label)}/)
- end
- end
- end
-
- describe 'when the collection objects don\'t respond to :to_label' do
- before do
- @fred.stub!(:respond_to?).with(:to_label).and_return(false)
- semantic_form_for(@new_post) do |builder|
- concat(builder.input(:author_id, :as => :radio))
+ Formtastic::SemanticFormBuilder.collection_label_methods.each do |label_method|
+ describe "when the collection objects respond to #{label_method}" do
+ before do
+ @fred.stub!(:respond_to?).and_return { |m| m.to_s == label_method }
+ Author.find(:all).each { |a| a.stub!(label_method).and_return('The Label Text') }
+ semantic_form_for(@new_post) do |builder|
+ concat(builder.input(:author_id, :as => :radio))
+ end
end
- end
- it 'should render the options with :to_s as the label as a fallback' do
- Author.find(:all).each do |author|
- output_buffer.should have_tag("form li fieldset ol li label", /#{Regexp.escape(author.to_s)}/)
+ it "should render the options with #{label_method} as the label" do
+ Author.find(:all).each do |author|
+ output_buffer.should have_tag("form li fieldset ol li label", /The Label Text/)
+ end
end
end
end
-
end
end
@@ -1010,39 +996,23 @@ def custom(arg1, arg2, options = {})
end
describe 'when the :label_method option is not provided' do
-
- describe 'and the collection objects respond to :to_label' do
- before do
- output_buffer.replace ''
- @fred.should_receive(:respond_to?).with(:to_label).and_return(true)
- semantic_form_for(@new_post) do |builder|
- concat(builder.input(:author_id, :as => :select))
- end
- end
-
- it 'should use to_label as the option value' do
- Author.find(:all).each do |author|
- output_buffer.should have_tag("form li select option", /#{author.to_label}/)
- end
- end
- end
-
- describe 'and the collection objects do not respond to :to_label' do
- before do
- output_buffer.replace ''
- @fred.should_receive(:respond_to?).with(:to_label).and_return(false)
- semantic_form_for(@new_post) do |builder|
- concat(builder.input(:author_id, :as => :select))
+ Formtastic::SemanticFormBuilder.collection_label_methods.each do |label_method|
+ describe "when the collection objects respond to #{label_method}" do
+ before do
+ @fred.stub!(:respond_to?).and_return { |m| m.to_s == label_method }
+ Author.find(:all).each { |a| a.stub!(label_method).and_return('The Label Text') }
+ semantic_form_for(@new_post) do |builder|
+ concat(builder.input(:author_id, :as => :select))
+ end
end
- end
- it 'should use to_s as the option value as a fallback' do
- Author.find(:all).each do |author|
- output_buffer.should have_tag("form li select option", /#{Regexp.escape(author.to_s)}/)
+ it "should render the options with #{label_method} as the label" do
+ Author.find(:all).each do |author|
+ output_buffer.should have_tag("form li select option", /The Label Text/)
+ end
end
end
end
-
end
describe 'when the :label_method option is provided' do

0 comments on commit 30cfc86

Please sign in to comment.