Finish component stack refactoring.

This commit is contained in:
José Valim 2009-12-10 11:23:48 -02:00
parent 7329eb4c72
commit 000156e2e2
12 changed files with 54 additions and 59 deletions

View File

@ -16,7 +16,8 @@ module SimpleForm
mattr_accessor :components mattr_accessor :components
@@components = [ @@components = [
SimpleForm::Components::Wrapper, SimpleForm::Components::Label, SimpleForm::Components::Wrapper, SimpleForm::Components::Label,
SimpleForm::Components::Input, SimpleForm::Components::Hint, SimpleForm::Components::Error SimpleForm::Components::Input, SimpleForm::Components::Hint,
SimpleForm::Components::Error
] ]
# The terminator sent to the last component # The terminator sent to the last component

View File

@ -1,7 +1,14 @@
module SimpleForm module SimpleForm
module Components module Components
# The component is the core of SimpleForm. SimpleForm can be customized simply
# with the addition of new components to the component stack. A component just
# need to be initialized with two values, the builder and the next component to
# be invoked and respond to call.
#
# The Base component is a raw component with some helpers and a default behavior
# of prepending the content available in the method content.
class Base class Base
attr_reader :builder, :attribute, :input_type, :options delegate :template, :object, :object_name, :attribute, :input_type, :options, :to => :@builder
def self.basename def self.basename
@basename ||= name.split("::").last.underscore.to_sym @basename ||= name.split("::").last.underscore.to_sym
@ -10,34 +17,19 @@ module SimpleForm
def initialize(builder, component) def initialize(builder, component)
@builder = builder @builder = builder
@component = component @component = component
@attribute = @builder.attribute
@input_type = @builder.input_type
@options = @builder.options
end end
def call def call
generate + @component.call return @component.call unless valid?
end content + @component.call
def generate
return "" unless valid?
component_tag(content).to_s
end end
def valid? def valid?
true true
end end
def template
@builder.template
end
def object
@builder.object
end
def hidden_input? def hidden_input?
@input_type == :hidden input_type == :hidden
end end
def basename def basename
@ -49,7 +41,7 @@ module SimpleForm
end end
def translate(default='') def translate(default='')
lookups = [ :"#{@builder.object_name}.#{@attribute}", :"#{@attribute}", default ] lookups = [ :"#{object_name}.#{attribute}", :"#{attribute}", default ]
I18n.t(lookups.shift, :scope => :"simple_form.#{basename.to_s.pluralize}", :default => lookups) I18n.t(lookups.shift, :scope => :"simple_form.#{basename.to_s.pluralize}", :default => lookups)
end end
end end

View File

@ -6,11 +6,11 @@ module SimpleForm
end end
def errors def errors
@errors ||= object.errors[@attribute] @errors ||= object.errors[attribute]
end end
def content def content
Array(errors).to_sentence component_tag Array(errors).to_sentence
end end
end end
end end

View File

@ -2,11 +2,15 @@ module SimpleForm
module Components module Components
class Hint < Base class Hint < Base
def valid? def valid?
!hidden_input? && !content.blank? !hidden_input? && !hint.blank?
end
def hint
@hint ||= options[:hint] || translate
end end
def content def content
@content ||= @options[:hint] || translate component_tag hint
end end
end end
end end

View File

@ -26,15 +26,15 @@ module SimpleForm
end end
end end
def generate def content
html_options = @options[:html] || {} html_options = options[:html] || {}
html_options[:class] = default_css_classes(html_options[:class]) html_options[:class] = default_css_classes(html_options[:class])
@options[:options] ||= {} options[:options] ||= {}
mapping = self.class.mappings[@input_type] mapping = self.class.mappings[input_type]
raise "Invalid input type #{@input_type.inspect}" unless mapping raise "Invalid input type #{input_type.inspect}" unless mapping
args = [ @attribute ] args = [ attribute ]
apply_collection_behavior(args) if mapping.collection apply_collection_behavior(args) if mapping.collection
apply_options_behavior(args) if mapping.options apply_options_behavior(args) if mapping.options
args << html_options args << html_options
@ -45,15 +45,15 @@ module SimpleForm
protected protected
def apply_collection_behavior(args) def apply_collection_behavior(args)
collection = (@options[:collection] || self.class.boolean_collection).to_a collection = (options[:collection] || self.class.boolean_collection).to_a
detect_collection_methods(collection, @options) detect_collection_methods(collection, options)
@options[:options][:include_blank] = true unless @options[:options].key?(:include_blank) options[:options][:include_blank] = true unless options[:options].key?(:include_blank)
args.push(collection, @options[:value_method], @options[:label_method]) args.push(collection, options[:value_method], options[:label_method])
end end
def apply_options_behavior(args) def apply_options_behavior(args)
args << @options[:options] args << options[:options]
end end
def detect_collection_methods(collection, options) def detect_collection_methods(collection, options)

View File

@ -28,15 +28,14 @@ module SimpleForm
!hidden_input? !hidden_input?
end end
def generate def content
return '' unless valid?
html_options = { :class => default_css_classes } html_options = { :class => default_css_classes }
html_options[:for] = @options[:html][:id] if @options.key?(:html) html_options[:for] = options[:html][:id] if options.key?(:html)
@builder.label(@attribute, label_text, html_options) @builder.label(attribute, label_text, html_options)
end end
def label_text def label_text
required_text << (@options[:label] || translate_label) required_text << (options[:label] || translate_label)
end end
def required_text def required_text
@ -44,7 +43,7 @@ module SimpleForm
end end
def translate_label def translate_label
default = object.try(:human_attribute_name, @attribute.to_s) || @attribute.to_s.humanize default = object.try(:human_attribute_name, attribute.to_s) || attribute.to_s.humanize
translate(default) translate(default)
end end
end end

View File

@ -1,6 +1,5 @@
module SimpleForm module SimpleForm
class FormBuilder < ActionView::Helpers::FormBuilder class FormBuilder < ActionView::Helpers::FormBuilder
# Make the template accessible for components
attr_reader :template, :object_name, :object, :attribute, :input_type, :options attr_reader :template, :object_name, :object, :attribute, :input_type, :options
def input(attribute, options={}) def input(attribute, options={})
@ -23,7 +22,7 @@ module SimpleForm
return :select if @options[:collection] return :select if @options[:collection]
input_type = if @object.respond_to?(:column_for_attribute) input_type = if @object.respond_to?(:column_for_attribute)
column = @object.column_for_attribute(attribute) column = @object.column_for_attribute(@attribute)
column.type if column column.type if column
end end
@ -31,7 +30,7 @@ module SimpleForm
when :timestamp when :timestamp
:datetime :datetime
when :string, nil when :string, nil
attribute.to_s =~ /password/ ? :password : :string @attribute.to_s =~ /password/ ? :password : :string
else else
input_type input_type
end end

View File

@ -1,7 +1,7 @@
module SimpleForm module SimpleForm
module RequiredHelpers module RequiredHelpers
def attribute_required? def attribute_required?
@options[:required] != false options[:required] != false
end end
def required_class def required_class
@ -9,11 +9,11 @@ module SimpleForm
end end
def attribute_required? def attribute_required?
@options[:required] != false options[:required] != false
end end
def default_css_classes(merge_class=nil) def default_css_classes(merge_class=nil)
"#{@input_type} #{required_class} #{merge_class}".strip "#{input_type} #{required_class} #{merge_class}".strip
end end
end end
end end

View File

@ -9,26 +9,26 @@ class ErrorTest < ActionView::TestCase
f.options = options f.options = options
error = SimpleForm::Components::Error.new(f, SimpleForm.terminator) error = SimpleForm::Components::Error.new(f, SimpleForm.terminator)
concat(error.generate) concat(error.call)
yield error if block_given? yield error if block_given?
end end
end end
test 'error should not generate content for hidden fields' do test 'error should not generate content for hidden fields' do
with_error_for @user, :name, :hidden do |error| with_error_for @user, :name, :hidden do |error|
assert error.generate.blank? assert error.call.blank?
end end
end end
test 'error should not generate content for attribute without errors' do test 'error should not generate content for attribute without errors' do
with_error_for @user, :active, :boolean do |error| with_error_for @user, :active, :boolean do |error|
assert error.generate.blank? assert error.call.blank?
end end
end end
test 'error should not generate messages when object is not present' do test 'error should not generate messages when object is not present' do
with_error_for :project, :name, :string do |error| with_error_for :project, :name, :string do |error|
assert error.generate.blank? assert error.call.blank?
end end
end end

View File

@ -9,20 +9,20 @@ class ErrorTest < ActionView::TestCase
f.options = options f.options = options
hint = SimpleForm::Components::Hint.new(f, SimpleForm.terminator) hint = SimpleForm::Components::Hint.new(f, SimpleForm.terminator)
concat(hint.generate) concat(hint.call)
yield hint if block_given? yield hint if block_given?
end end
end end
test 'hint should not be generated by default' do test 'hint should not be generated by default' do
with_hint_for @user, :name, :string do |hint| with_hint_for @user, :name, :string do |hint|
assert hint.generate.blank? assert hint.call.blank?
end end
end end
test 'hint should not be generated for hidden fields' do test 'hint should not be generated for hidden fields' do
with_hint_for @user, :name, :hidden, :hint => 'Use with care...' do |hint| with_hint_for @user, :name, :hidden, :hint => 'Use with care...' do |hint|
assert hint.generate.blank? assert hint.call.blank?
end end
end end

View File

@ -13,7 +13,7 @@ class InputTest < ActionView::TestCase
f.options = options f.options = options
input = SimpleForm::Components::Input.new(f, SimpleForm.terminator) input = SimpleForm::Components::Input.new(f, SimpleForm.terminator)
concat(input.generate) concat(input.call)
yield input if block_given? yield input if block_given?
end end
end end

View File

@ -15,14 +15,14 @@ class LabelTest < ActionView::TestCase
f.options = options f.options = options
label = SimpleForm::Components::Label.new(f, SimpleForm.terminator) label = SimpleForm::Components::Label.new(f, SimpleForm.terminator)
concat(label.generate) concat(label.call)
yield label if block_given? yield label if block_given?
end end
end end
test 'label should not be generated for hidden inputs' do test 'label should not be generated for hidden inputs' do
with_label_for @user, :name, :hidden do |label| with_label_for @user, :name, :hidden do |label|
assert label.generate.blank? assert label.call.blank?
end end
end end