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
@@components = [
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

View File

@ -1,7 +1,14 @@
module SimpleForm
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
attr_reader :builder, :attribute, :input_type, :options
delegate :template, :object, :object_name, :attribute, :input_type, :options, :to => :@builder
def self.basename
@basename ||= name.split("::").last.underscore.to_sym
@ -10,34 +17,19 @@ module SimpleForm
def initialize(builder, component)
@builder = builder
@component = component
@attribute = @builder.attribute
@input_type = @builder.input_type
@options = @builder.options
end
def call
generate + @component.call
end
def generate
return "" unless valid?
component_tag(content).to_s
return @component.call unless valid?
content + @component.call
end
def valid?
true
end
def template
@builder.template
end
def object
@builder.object
end
def hidden_input?
@input_type == :hidden
input_type == :hidden
end
def basename
@ -49,7 +41,7 @@ module SimpleForm
end
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)
end
end

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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