Code refactoring finished. Now tests one.
This commit is contained in:
parent
42830967d7
commit
7d7c6cda72
|
@ -3,17 +3,17 @@ require 'simple_form/action_view_extensions/builder'
|
|||
require 'simple_form/action_view_extensions/instance_tag'
|
||||
|
||||
module SimpleForm
|
||||
autoload :Components, 'simple_form/components'
|
||||
autoload :FormBuilder, 'simple_form/form_builder'
|
||||
autoload :I18nCache, 'simple_form/i18n_cache'
|
||||
autoload :MapType, 'simple_form/map_type'
|
||||
autoload :RequiredHelpers, 'simple_form/required_helpers'
|
||||
autoload :Components, 'simple_form/components'
|
||||
autoload :FormBuilder, 'simple_form/form_builder'
|
||||
autoload :I18nCache, 'simple_form/i18n_cache'
|
||||
autoload :Inputs, 'simple_form/inputs'
|
||||
autoload :MapType, 'simple_form/map_type'
|
||||
|
||||
# Default tag used in hints
|
||||
# Default tag used in hints.
|
||||
mattr_accessor :hint_tag
|
||||
@@hint_tag = :span
|
||||
|
||||
# Default tag used in errors
|
||||
# Default tag used in errors.
|
||||
mattr_accessor :error_tag
|
||||
@@error_tag = :span
|
||||
|
||||
|
@ -21,11 +21,11 @@ module SimpleForm
|
|||
mattr_accessor :components
|
||||
@@components = [ :label, :input, :hint, :error ]
|
||||
|
||||
# Series of attemps to detect a default label method for collection
|
||||
# Series of attemps to detect a default label method for collection.
|
||||
mattr_accessor :collection_label_methods
|
||||
@@collection_label_methods = [ :to_label, :name, :title, :to_s ]
|
||||
|
||||
# Series of attemps to detect a default value method for collection
|
||||
# Series of attemps to detect a default value method for collection.
|
||||
mattr_accessor :collection_value_methods
|
||||
@@collection_value_methods = [ :id, :to_s ]
|
||||
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
module SimpleForm
|
||||
module Components
|
||||
autoload :Errors, 'simple_form/components/errors'
|
||||
autoload :Hints, 'simple_form/components/hints'
|
||||
autoload :Labels, 'simple_form/components/labels'
|
||||
autoload :Wrapper, 'simple_form/components/wrapper'
|
||||
end
|
||||
end
|
|
@ -0,0 +1,35 @@
|
|||
module SimpleForm
|
||||
module Components
|
||||
module Errors
|
||||
def error
|
||||
template.content_tag(error_tag, error_text, error_html_options) if object && errors.present?
|
||||
end
|
||||
|
||||
def error_tag
|
||||
options[:error_tag] || SimpleForm.error_tag
|
||||
end
|
||||
|
||||
def error_text
|
||||
errors.to_sentence
|
||||
end
|
||||
|
||||
def error_html_options
|
||||
html_options_for(:error, :error)
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def errors
|
||||
@errors ||= (errors_on_attribute + errors_on_association).compact
|
||||
end
|
||||
|
||||
def errors_on_attribute
|
||||
Array(object.errors[attribute_name])
|
||||
end
|
||||
|
||||
def errors_on_association
|
||||
reflection ? Array(object.errors[reflection.name]) : []
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,21 @@
|
|||
module SimpleForm
|
||||
module Components
|
||||
module Hints
|
||||
def hint
|
||||
template.content_tag(hint_tag, hint_text, hint_html_options) unless hint_text.blank?
|
||||
end
|
||||
|
||||
def hint_tag
|
||||
options[:hint_tag] || SimpleForm.hint_tag
|
||||
end
|
||||
|
||||
def hint_text
|
||||
@hint_text ||= options[:hint] || translate(:hints)
|
||||
end
|
||||
|
||||
def hint_html_options
|
||||
html_options_for(:hint, :hint)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,68 @@
|
|||
module SimpleForm
|
||||
module Components
|
||||
module Labels
|
||||
def self.included(base)
|
||||
base.extend ClassMethods
|
||||
end
|
||||
|
||||
module ClassMethods #:nodoc:
|
||||
def translate_required_html
|
||||
i18n_cache :translate_required_html do
|
||||
I18n.t(:"simple_form.required.html", :default =>
|
||||
%[<abbr title="#{translate_required_text}">#{translate_required_mark}</abbr>]
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
def translate_required_text
|
||||
I18n.t(:"simple_form.required.text", :default => 'required')
|
||||
end
|
||||
|
||||
def translate_required_mark
|
||||
I18n.t(:"simple_form.required.mark", :default => '*')
|
||||
end
|
||||
end
|
||||
|
||||
def label
|
||||
@builder.label(label_target, label_text, label_html_options)
|
||||
end
|
||||
|
||||
def label_text
|
||||
SimpleForm.label_text.call(raw_label_text, required_label_text)
|
||||
end
|
||||
|
||||
def label_target
|
||||
attribute_name
|
||||
end
|
||||
|
||||
def label_html_options
|
||||
label_options = html_options_for(:label, input_type, required_class)
|
||||
label_options[:for] = options[:input_html][:id] if options.key?(:input_html)
|
||||
label_options
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def raw_label_text #:nodoc:
|
||||
options[:label] || label_translation
|
||||
end
|
||||
|
||||
# Default required text when attribute is required.
|
||||
def required_label_text #:nodoc:
|
||||
attribute_required? ? self.class.translate_required_html.dup : ''
|
||||
end
|
||||
|
||||
# First check human attribute name and then labels.
|
||||
# TODO Remove me in Rails > 2.3.5
|
||||
def label_translation #:nodoc:
|
||||
default = if object.class.respond_to?(:human_attribute_name)
|
||||
object.class.human_attribute_name(reflection_or_attribute_name.to_s)
|
||||
else
|
||||
attribute_name.to_s.humanize
|
||||
end
|
||||
|
||||
translate(:labels, default)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,21 @@
|
|||
module SimpleForm
|
||||
module Components
|
||||
module Wrapper
|
||||
def wrap(content)
|
||||
if wrapper_tag && options[:wrapper] != false
|
||||
template.content_tag(wrapper_tag, content, wrapper_html_options)
|
||||
else
|
||||
content
|
||||
end
|
||||
end
|
||||
|
||||
def wrapper_tag
|
||||
options[:wrapper_tag] || SimpleForm.wrapper_tag
|
||||
end
|
||||
|
||||
def wrapper_html_options
|
||||
html_options_for(:wrapper, input_type, required_class)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -3,6 +3,15 @@ module SimpleForm
|
|||
attr_reader :template, :object_name, :object, :attribute_name, :column,
|
||||
:reflection, :input_type, :options
|
||||
|
||||
extend MapType
|
||||
include SimpleForm::Inputs
|
||||
|
||||
map_type :boolean, :password, :text, :file, :to => SimpleForm::Inputs::MappingInput
|
||||
map_type :string, :integer, :decimal, :float, :to => SimpleForm::Inputs::TextFieldInput
|
||||
map_type :select, :radio, :check_boxes, :to => SimpleForm::Inputs::CollectionInput
|
||||
map_type :date, :time, :datetime, :to => SimpleForm::Inputs::DateTimeInput
|
||||
map_type :country, :time_zone, :to => SimpleForm::Inputs::PriorityInput
|
||||
|
||||
# Basic input helper, combines all components in the stack to generate
|
||||
# input html based on options the user define and some guesses through
|
||||
# database column information. By default a call to input will generate
|
||||
|
@ -68,365 +77,6 @@ module SimpleForm
|
|||
# Some inputs, as :time_zone and :country accepts a :priority option. If none is
|
||||
# given SimpleForm.time_zone_priority and SimpleForm.country_priority are used respectivelly.
|
||||
#
|
||||
module Labels
|
||||
def self.included(base)
|
||||
base.extend ClassMethods
|
||||
end
|
||||
|
||||
module ClassMethods #:nodoc:
|
||||
def translate_required_html
|
||||
i18n_cache :translate_required_html do
|
||||
I18n.t(:"simple_form.required.html", :default =>
|
||||
%[<abbr title="#{translate_required_text}">#{translate_required_mark}</abbr>]
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
def translate_required_text
|
||||
I18n.t(:"simple_form.required.text", :default => 'required')
|
||||
end
|
||||
|
||||
def translate_required_mark
|
||||
I18n.t(:"simple_form.required.mark", :default => '*')
|
||||
end
|
||||
end
|
||||
|
||||
def label
|
||||
@builder.label(label_target, label_text, label_html_options)
|
||||
end
|
||||
|
||||
def label_text
|
||||
SimpleForm.label_text.call(raw_label_text, required_label_text)
|
||||
end
|
||||
|
||||
def label_target
|
||||
attribute_name
|
||||
end
|
||||
|
||||
def label_html_options
|
||||
label_options = html_options_for(:label, input_type, required_class)
|
||||
label_options[:for] = options[:input_html][:id] if options.key?(:input_html)
|
||||
label_options
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def raw_label_text #:nodoc:
|
||||
options[:label] || label_translation
|
||||
end
|
||||
|
||||
# Default required text when attribute is required.
|
||||
def required_label_text #:nodoc:
|
||||
attribute_required? ? self.class.translate_required_html.dup : ''
|
||||
end
|
||||
|
||||
# First check human attribute name and then labels.
|
||||
# TODO Remove me in Rails > 2.3.5
|
||||
def label_translation #:nodoc:
|
||||
default = if object.class.respond_to?(:human_attribute_name)
|
||||
object.class.human_attribute_name(reflection_or_attribute_name.to_s)
|
||||
else
|
||||
attribute_name.to_s.humanize
|
||||
end
|
||||
|
||||
translate(:labels, default)
|
||||
end
|
||||
end
|
||||
|
||||
module Hints
|
||||
def hint
|
||||
template.content_tag(hint_tag, hint_text, hint_html_options) unless hint_text.blank?
|
||||
end
|
||||
|
||||
def hint_tag
|
||||
options[:hint_tag] || SimpleForm.hint_tag
|
||||
end
|
||||
|
||||
def hint_text
|
||||
@hint_text ||= options[:hint] || translate(:hints)
|
||||
end
|
||||
|
||||
def hint_html_options
|
||||
html_options_for(:hint, :hint)
|
||||
end
|
||||
end
|
||||
|
||||
module Errors
|
||||
def error
|
||||
template.content_tag(error_tag, error_text, error_html_options) if object && errors.present?
|
||||
end
|
||||
|
||||
def error_tag
|
||||
options[:error_tag] || SimpleForm.error_tag
|
||||
end
|
||||
|
||||
def error_text
|
||||
errors.to_sentence
|
||||
end
|
||||
|
||||
def error_html_options
|
||||
html_options_for(:error, :error)
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def errors
|
||||
@errors ||= (errors_on_attribute + errors_on_association).compact
|
||||
end
|
||||
|
||||
def errors_on_attribute
|
||||
Array(object.errors[attribute_name])
|
||||
end
|
||||
|
||||
def errors_on_association
|
||||
reflection ? Array(object.errors[reflection.name]) : []
|
||||
end
|
||||
end
|
||||
|
||||
class Base
|
||||
extend I18nCache
|
||||
|
||||
include Errors
|
||||
include Hints
|
||||
include Labels
|
||||
|
||||
delegate :template, :object, :object_name, :attribute_name, :column,
|
||||
:reflection, :input_type, :options, :to => :@builder
|
||||
|
||||
def initialize(builder)
|
||||
@builder = builder
|
||||
end
|
||||
|
||||
def input
|
||||
raise NotImplemented
|
||||
end
|
||||
|
||||
def input_options
|
||||
options[:include_blank] = true unless skip_include_blank?
|
||||
options
|
||||
end
|
||||
|
||||
def input_html_options
|
||||
html_options_for(:input, input_type, required_class)
|
||||
end
|
||||
|
||||
def render
|
||||
pieces = SimpleForm.components.select { |n| n unless @builder.options[n] == false }
|
||||
content = pieces.map!{ |p| send(p).to_s }.join
|
||||
wrap(content)
|
||||
end
|
||||
|
||||
def wrap(content)
|
||||
if wrapper_tag && options[:wrapper] != false
|
||||
template.content_tag(wrapper_tag, content, wrapper_html_options)
|
||||
else
|
||||
content
|
||||
end
|
||||
end
|
||||
|
||||
def wrapper_tag
|
||||
options[:wrapper_tag] || SimpleForm.wrapper_tag
|
||||
end
|
||||
|
||||
def wrapper_html_options
|
||||
html_options_for(:wrapper, input_type, required_class)
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
# When action is create or update, we still should use new and edit
|
||||
ACTIONS = {
|
||||
:create => :new,
|
||||
:update => :edit
|
||||
}
|
||||
|
||||
def attribute_required?
|
||||
options[:required] != false
|
||||
end
|
||||
|
||||
def required_class
|
||||
attribute_required? ? :required : :optional
|
||||
end
|
||||
|
||||
# Find reflection name when available, otherwise use attribute
|
||||
def reflection_or_attribute_name
|
||||
reflection ? reflection.name : attribute_name
|
||||
end
|
||||
|
||||
# Check if :include_blank must be included by default.
|
||||
def skip_include_blank?
|
||||
options.key?(:prompt) || options.key?(:include_blank)
|
||||
end
|
||||
|
||||
# Retrieve options for the given namespace from the options hash
|
||||
def html_options_for(namespace, *extra)
|
||||
html_options = options[:"#{namespace}_html"] || {}
|
||||
html_options[:class] = (extra << html_options[:class]).join(' ').strip if extra.present?
|
||||
html_options
|
||||
end
|
||||
|
||||
# Lookup translations for the given namespace using I18n, based on object name,
|
||||
# actual action and attribute name. Lookup priority as follows:
|
||||
#
|
||||
# simple_form.{namespace}.{model}.{action}.{attribute}
|
||||
# simple_form.{namespace}.{model}.{attribute}
|
||||
# simple_form.{namespace}.{attribute}
|
||||
#
|
||||
# Namespace is used for :labels and :hints.
|
||||
#
|
||||
# Model is the actual object name, for a @user object you'll have :user.
|
||||
# Action is the action being rendered, usually :new or :edit.
|
||||
# And attribute is the attribute itself, :name for example.
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# simple_form:
|
||||
# labels:
|
||||
# user:
|
||||
# new:
|
||||
# email: 'E-mail para efetuar o sign in.'
|
||||
# edit:
|
||||
# email: 'E-mail.'
|
||||
#
|
||||
# Take a look at our locale example file.
|
||||
def translate(namespace, default='')
|
||||
lookups = []
|
||||
lookups << :"#{object_name}.#{lookup_action}.#{reflection_or_attribute_name}"
|
||||
lookups << :"#{object_name}.#{reflection_or_attribute_name}"
|
||||
lookups << :"#{reflection_or_attribute_name}"
|
||||
lookups << default
|
||||
I18n.t(lookups.shift, :scope => :"simple_form.#{namespace}", :default => lookups)
|
||||
end
|
||||
|
||||
# The action to be used in lookup.
|
||||
def lookup_action
|
||||
action = template.controller.action_name.to_sym
|
||||
ACTIONS[action] || action
|
||||
end
|
||||
end
|
||||
|
||||
# Uses MapType to handle basic input types.
|
||||
class MappingInput < Base
|
||||
extend MapType
|
||||
|
||||
map_type :boolean, :to => :check_box
|
||||
map_type :password, :to => :password_field
|
||||
map_type :text, :to => :text_area
|
||||
map_type :file, :to => :file_field
|
||||
|
||||
def input
|
||||
@builder.send(input_method, attribute_name, input_html_options)
|
||||
end
|
||||
|
||||
def input_method
|
||||
method = self.class.mappings[input_type]
|
||||
raise "Could not find method for #{input_type.inspect}" unless method
|
||||
method
|
||||
end
|
||||
end
|
||||
|
||||
# Handles common text field inputs, as String, Numeric, Float and Decimal.
|
||||
class TextFieldInput < Base
|
||||
def input
|
||||
@builder.text_field(attribute_name, input_html_options)
|
||||
end
|
||||
|
||||
def input_html_options
|
||||
input_options = super
|
||||
input_options[:max_length] ||= column.limit if column
|
||||
input_options
|
||||
end
|
||||
end
|
||||
|
||||
class DateTimeInput < Base
|
||||
def input
|
||||
@builder.send(:"#{input_type}_select", attribute_name, input_options, input_html_options)
|
||||
end
|
||||
|
||||
def label_target
|
||||
case input_type
|
||||
when :date, :datetime
|
||||
"#{attribute_name}_1i"
|
||||
when :time
|
||||
"#{attribute_name}_4i"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class CollectionInput < Base
|
||||
# Default boolean collection for use with selects/radios when no
|
||||
# collection is given. Always fallback to this boolean collection.
|
||||
# Texts can be translated using i18n in "simple_form.true" and
|
||||
# "simple_form.false" keys. See the example locale file.
|
||||
def self.boolean_collection
|
||||
i18n_cache :boolean_collection do
|
||||
[ [I18n.t(:"simple_form.yes", :default => 'Yes'), true],
|
||||
[I18n.t(:"simple_form.no", :default => 'No'), false] ]
|
||||
end
|
||||
end
|
||||
|
||||
def input
|
||||
collection = (options[:collection] || self.class.boolean_collection).to_a
|
||||
detect_collection_methods(collection, options)
|
||||
@builder.send(:"collection_#{input_type}", attribute_name, collection, options[:value_method],
|
||||
options[:label_method], input_options, input_html_options)
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def skip_include_blank?
|
||||
super || options[:input_html].try(:[], :multiple)
|
||||
end
|
||||
|
||||
# Detect the right method to find the label and value for a collection.
|
||||
# If no label or value method are defined, will attempt to find them based
|
||||
# on default label and value methods that can be configured through
|
||||
# SimpleForm.collection_label_methods and
|
||||
# SimpleForm.collection_value_methods.
|
||||
def detect_collection_methods(collection, options)
|
||||
sample = collection.first || collection.last
|
||||
|
||||
case sample
|
||||
when Array
|
||||
label, value = :first, :last
|
||||
when Integer
|
||||
label, value = :to_s, :to_i
|
||||
when String, NilClass
|
||||
label, value = :to_s, :to_s
|
||||
end
|
||||
|
||||
options[:label_method] ||= label || SimpleForm.collection_label_methods.find { |m| sample.respond_to?(m) }
|
||||
options[:value_method] ||= value || SimpleForm.collection_value_methods.find { |m| sample.respond_to?(m) }
|
||||
end
|
||||
end
|
||||
|
||||
# Handles hidden input.
|
||||
class HiddenInput < Base
|
||||
def render
|
||||
@builder.hidden_field(attribute_name, input_html_options)
|
||||
end
|
||||
end
|
||||
|
||||
class PriorityInput < Base
|
||||
def input
|
||||
@builder.send(:"#{input_type}_select", attribute_name, input_priority,
|
||||
input_options, input_html_options)
|
||||
end
|
||||
|
||||
def input_priority
|
||||
options[:priority] || SimpleForm.send(:"#{input_type}_priority")
|
||||
end
|
||||
end
|
||||
|
||||
extend MapType
|
||||
|
||||
map_type :boolean, :password, :text, :file, :to => MappingInput
|
||||
map_type :hidden, :to => HiddenInput # TODO This should be automatic
|
||||
map_type :string, :integer, :decimal, :float, :to => TextFieldInput
|
||||
map_type :select, :radio, :check_boxes, :to => CollectionInput
|
||||
map_type :date, :time, :datetime, :to => DateTimeInput
|
||||
map_type :country, :time_zone, :to => PriorityInput
|
||||
|
||||
def input(attribute_name, options={})
|
||||
define_simple_form_attributes(attribute_name, options)
|
||||
|
||||
|
@ -566,7 +216,7 @@ module SimpleForm
|
|||
#
|
||||
def error(attribute_name, options={})
|
||||
define_simple_form_attributes(attribute_name, :error_html => options)
|
||||
Base.new(self).error
|
||||
SimpleForm::Inputs::Base.new(self).error
|
||||
end
|
||||
|
||||
# Creates a hint tag for the given attribute. Accepts a symbol indicating
|
||||
|
@ -582,7 +232,7 @@ module SimpleForm
|
|||
def hint(attribute_name, options={})
|
||||
attribute_name, options[:hint] = nil, attribute_name if attribute_name.is_a?(String)
|
||||
define_simple_form_attributes(attribute_name, :hint => options.delete(:hint), :hint_html => options)
|
||||
Base.new(self).hint
|
||||
SimpleForm::Inputs::Base.new(self).hint
|
||||
end
|
||||
|
||||
# Creates a default label tag for the given attribute. You can give a label
|
||||
|
@ -603,7 +253,7 @@ module SimpleForm
|
|||
options = args.extract_options!
|
||||
define_simple_form_attributes(attribute_name, :label => options.delete(:label),
|
||||
:label_html => options, :required => options.delete(:required))
|
||||
Base.new(self).label
|
||||
SimpleForm::Inputs::Base.new(self).label
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
module SimpleForm
|
||||
module Inputs
|
||||
autoload :Base, 'simple_form/inputs/base'
|
||||
autoload :CollectionInput, 'simple_form/inputs/collection_input'
|
||||
autoload :DateTimeInput, 'simple_form/inputs/date_time_input'
|
||||
autoload :HiddenInput, 'simple_form/inputs/hidden_input'
|
||||
autoload :MappingInput, 'simple_form/inputs/mapping_input'
|
||||
autoload :PriorityInput, 'simple_form/inputs/priority_input'
|
||||
autoload :TextFieldInput, 'simple_form/inputs/text_field_input'
|
||||
end
|
||||
end
|
|
@ -0,0 +1,113 @@
|
|||
module SimpleForm
|
||||
module Inputs
|
||||
class Base
|
||||
extend I18nCache
|
||||
|
||||
# When action is create or update, we still should use new and edit
|
||||
ACTIONS = {
|
||||
:create => :new,
|
||||
:update => :edit
|
||||
}
|
||||
|
||||
include SimpleForm::Components::Errors
|
||||
include SimpleForm::Components::Hints
|
||||
include SimpleForm::Components::Labels
|
||||
include SimpleForm::Components::Wrapper
|
||||
|
||||
delegate :template, :object, :object_name, :attribute_name, :column,
|
||||
:reflection, :input_type, :options, :to => :@builder
|
||||
|
||||
def initialize(builder)
|
||||
@builder = builder
|
||||
end
|
||||
|
||||
def input
|
||||
raise NotImplementedError
|
||||
end
|
||||
|
||||
def input_options
|
||||
options[:include_blank] = true unless skip_include_blank?
|
||||
options
|
||||
end
|
||||
|
||||
def input_html_options
|
||||
html_options_for(:input, input_type, required_class)
|
||||
end
|
||||
|
||||
def render
|
||||
content = SimpleForm.components.map do |component|
|
||||
next if options[component] == false
|
||||
send(component)
|
||||
end
|
||||
content.compact!
|
||||
wrap(content.join)
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def attribute_required?
|
||||
options[:required] != false
|
||||
end
|
||||
|
||||
def required_class
|
||||
attribute_required? ? :required : :optional
|
||||
end
|
||||
|
||||
# Find reflection name when available, otherwise use attribute
|
||||
def reflection_or_attribute_name
|
||||
reflection ? reflection.name : attribute_name
|
||||
end
|
||||
|
||||
# Check if :include_blank must be included by default.
|
||||
def skip_include_blank?
|
||||
options.key?(:prompt) || options.key?(:include_blank)
|
||||
end
|
||||
|
||||
# Retrieve options for the given namespace from the options hash
|
||||
def html_options_for(namespace, *extra)
|
||||
html_options = options[:"#{namespace}_html"] || {}
|
||||
html_options[:class] = (extra << html_options[:class]).join(' ').strip if extra.present?
|
||||
html_options
|
||||
end
|
||||
|
||||
# Lookup translations for the given namespace using I18n, based on object name,
|
||||
# actual action and attribute name. Lookup priority as follows:
|
||||
#
|
||||
# simple_form.{namespace}.{model}.{action}.{attribute}
|
||||
# simple_form.{namespace}.{model}.{attribute}
|
||||
# simple_form.{namespace}.{attribute}
|
||||
#
|
||||
# Namespace is used for :labels and :hints.
|
||||
#
|
||||
# Model is the actual object name, for a @user object you'll have :user.
|
||||
# Action is the action being rendered, usually :new or :edit.
|
||||
# And attribute is the attribute itself, :name for example.
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# simple_form:
|
||||
# labels:
|
||||
# user:
|
||||
# new:
|
||||
# email: 'E-mail para efetuar o sign in.'
|
||||
# edit:
|
||||
# email: 'E-mail.'
|
||||
#
|
||||
# Take a look at our locale example file.
|
||||
def translate(namespace, default='')
|
||||
lookups = []
|
||||
lookups << :"#{object_name}.#{lookup_action}.#{reflection_or_attribute_name}"
|
||||
lookups << :"#{object_name}.#{reflection_or_attribute_name}"
|
||||
lookups << :"#{reflection_or_attribute_name}"
|
||||
lookups << default
|
||||
I18n.t(lookups.shift, :scope => :"simple_form.#{namespace}", :default => lookups)
|
||||
end
|
||||
|
||||
# The action to be used in lookup.
|
||||
def lookup_action
|
||||
action = template.controller.action_name.to_sym
|
||||
ACTIONS[action] || action
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,50 @@
|
|||
module SimpleForm
|
||||
module Inputs
|
||||
class CollectionInput < Base
|
||||
# Default boolean collection for use with selects/radios when no
|
||||
# collection is given. Always fallback to this boolean collection.
|
||||
# Texts can be translated using i18n in "simple_form.yes" and
|
||||
# "simple_form.no" keys. See the example locale file.
|
||||
def self.boolean_collection
|
||||
i18n_cache :boolean_collection do
|
||||
[ [I18n.t(:"simple_form.yes", :default => 'Yes'), true],
|
||||
[I18n.t(:"simple_form.no", :default => 'No'), false] ]
|
||||
end
|
||||
end
|
||||
|
||||
def input
|
||||
collection = (options[:collection] || self.class.boolean_collection).to_a
|
||||
detect_collection_methods(collection, options)
|
||||
@builder.send(:"collection_#{input_type}", attribute_name, collection, options[:value_method],
|
||||
options[:label_method], input_options, input_html_options)
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def skip_include_blank?
|
||||
super || options[:input_html].try(:[], :multiple)
|
||||
end
|
||||
|
||||
# Detect the right method to find the label and value for a collection.
|
||||
# If no label or value method are defined, will attempt to find them based
|
||||
# on default label and value methods that can be configured through
|
||||
# SimpleForm.collection_label_methods and
|
||||
# SimpleForm.collection_value_methods.
|
||||
def detect_collection_methods(collection, options)
|
||||
sample = collection.first || collection.last
|
||||
|
||||
case sample
|
||||
when Array
|
||||
label, value = :first, :last
|
||||
when Integer
|
||||
label, value = :to_s, :to_i
|
||||
when String, NilClass
|
||||
label, value = :to_s, :to_s
|
||||
end
|
||||
|
||||
options[:label_method] ||= label || SimpleForm.collection_label_methods.find { |m| sample.respond_to?(m) }
|
||||
options[:value_method] ||= value || SimpleForm.collection_value_methods.find { |m| sample.respond_to?(m) }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,18 @@
|
|||
module SimpleForm
|
||||
module Inputs
|
||||
class DateTimeInput < Base
|
||||
def input
|
||||
@builder.send(:"#{input_type}_select", attribute_name, input_options, input_html_options)
|
||||
end
|
||||
|
||||
def label_target
|
||||
case input_type
|
||||
when :date, :datetime
|
||||
"#{attribute_name}_1i"
|
||||
when :time
|
||||
"#{attribute_name}_4i"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,11 @@
|
|||
module SimpleForm
|
||||
module Inputs
|
||||
# Handles hidden input.
|
||||
class HiddenInput < Base
|
||||
def render
|
||||
@builder.hidden_field(attribute_name, input_html_options)
|
||||
end
|
||||
alias :input :render
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,23 @@
|
|||
module SimpleForm
|
||||
module Inputs
|
||||
# Uses MapType to handle basic input types.
|
||||
class MappingInput < Base
|
||||
extend MapType
|
||||
|
||||
map_type :boolean, :to => :check_box
|
||||
map_type :password, :to => :password_field
|
||||
map_type :text, :to => :text_area
|
||||
map_type :file, :to => :file_field
|
||||
|
||||
def input
|
||||
@builder.send(input_method, attribute_name, input_html_options)
|
||||
end
|
||||
|
||||
def input_method
|
||||
method = self.class.mappings[input_type]
|
||||
raise "Could not find method for #{input_type.inspect}" unless method
|
||||
method
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,14 @@
|
|||
module SimpleForm
|
||||
module Inputs
|
||||
class PriorityInput < Base
|
||||
def input
|
||||
@builder.send(:"#{input_type}_select", attribute_name, input_priority,
|
||||
input_options, input_html_options)
|
||||
end
|
||||
|
||||
def input_priority
|
||||
options[:priority] || SimpleForm.send(:"#{input_type}_priority")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,16 @@
|
|||
module SimpleForm
|
||||
module Inputs
|
||||
# Handles common text field inputs, as String, Numeric, Float and Decimal.
|
||||
class TextFieldInput < Base
|
||||
def input
|
||||
@builder.text_field(attribute_name, input_html_options)
|
||||
end
|
||||
|
||||
def input_html_options
|
||||
input_options = super
|
||||
input_options[:max_length] ||= column.limit if column
|
||||
input_options
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,26 +0,0 @@
|
|||
module SimpleForm
|
||||
module RequiredHelpers
|
||||
# Attribute is always required, unless the user has defined the opposite.
|
||||
def attribute_required?
|
||||
options[:required] != false
|
||||
end
|
||||
|
||||
def required_class
|
||||
attribute_required? ? :required : :optional
|
||||
end
|
||||
|
||||
# Creates default required classes for attributes, such as .string and
|
||||
# .decimal, based on input type, and required class
|
||||
def default_css_classes(merge_class=nil)
|
||||
"#{input_type} #{required_class} #{merge_class}".strip
|
||||
end
|
||||
|
||||
# When components may be required, default component html options always
|
||||
# must include default css classes.
|
||||
def component_html_options
|
||||
html_options = super
|
||||
html_options[:class] = default_css_classes(html_options[:class])
|
||||
html_options
|
||||
end
|
||||
end
|
||||
end
|
|
@ -9,7 +9,7 @@ class ErrorTest < ActionView::TestCase
|
|||
f.input_type = type
|
||||
f.options = options
|
||||
|
||||
concat(SimpleForm::FormBuilder::Base.new(f).error)
|
||||
concat(SimpleForm::Inputs::Base.new(f).error)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ class HintTest < ActionView::TestCase
|
|||
f.input_type = type
|
||||
f.options = options
|
||||
|
||||
concat(SimpleForm::FormBuilder::Base.new(f).hint)
|
||||
concat(SimpleForm::Inputs::Base.new(f).hint)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -3,329 +3,329 @@ require 'test_helper'
|
|||
class InputTest < ActionView::TestCase
|
||||
|
||||
setup do
|
||||
SimpleForm::Components::Input.reset_i18n_cache :boolean_collection
|
||||
SimpleForm::Inputs::Base.reset_i18n_cache :boolean_collection
|
||||
end
|
||||
|
||||
def with_input_for(object, attribute_name, type, options={})
|
||||
simple_form_for object do |f|
|
||||
f.attribute_name = attribute_name
|
||||
f.column = object.column_for_attribute(attribute_name) if object.respond_to?(:column_for_attribute)
|
||||
f.input_type = type
|
||||
f.options = options
|
||||
|
||||
klass = SimpleForm::FormBuilder.mappings[type]
|
||||
klass ||= SimpleForm::Inputs.const_get(:"#{type.to_s.camelize}Input")
|
||||
concat(klass.new(f).input)
|
||||
end
|
||||
end
|
||||
|
||||
test 'input should map text field to string attribute' do
|
||||
with_input_for @user, :name, :string
|
||||
assert_select 'input[name=\'user[name]\'][id=user_name][value=New in Simple Form!]'
|
||||
end
|
||||
|
||||
test 'input should generate css class based on default input type' do
|
||||
with_input_for @user, :name, :string
|
||||
assert_select 'input.string'
|
||||
with_input_for @user, :description, :text
|
||||
assert_select 'textarea.text'
|
||||
with_input_for @user, :age, :integer
|
||||
assert_select 'input.integer'
|
||||
with_input_for @user, :born_at, :date
|
||||
assert_select 'select.date'
|
||||
with_input_for @user, :created_at, :datetime
|
||||
assert_select 'select.datetime'
|
||||
end
|
||||
|
||||
test 'input should allow passing options to text field' do
|
||||
with_input_for @user, :name, :string, :input_html => { :class => 'my_input', :id => 'my_input' }
|
||||
assert_select 'input#my_input.my_input'
|
||||
end
|
||||
|
||||
test 'input should generate a text area for text attributes' do
|
||||
with_input_for @user, :description, :text
|
||||
assert_select 'textarea.text#user_description'
|
||||
end
|
||||
|
||||
test 'input should generate an integer text field for integer attributes ' do
|
||||
with_input_for @user, :age, :integer
|
||||
assert_select 'input.integer#user_age'
|
||||
end
|
||||
|
||||
test 'input should generate a float text field for float attributes ' do
|
||||
with_input_for @user, :age, :float
|
||||
assert_select 'input.float#user_age'
|
||||
end
|
||||
|
||||
test 'input should generate a decimal text field for decimal attributes ' do
|
||||
with_input_for @user, :age, :decimal
|
||||
assert_select 'input.decimal#user_age'
|
||||
end
|
||||
|
||||
test 'input should generate a checkbox by default for boolean attributes' do
|
||||
with_input_for @user, :active, :boolean
|
||||
assert_select 'input[type=checkbox].boolean#user_active'
|
||||
end
|
||||
|
||||
test 'input should generate a password field for password attributes' do
|
||||
with_input_for @user, :password, :password
|
||||
assert_select 'input[type=password].password#user_password'
|
||||
end
|
||||
|
||||
test 'input should generate a hidden field' do
|
||||
with_input_for @user, :name, :hidden
|
||||
assert_no_select 'input[type=text]'
|
||||
assert_select 'input#user_name[type=hidden]'
|
||||
end
|
||||
|
||||
test 'input should generate a file field' do
|
||||
with_input_for @user, :name, :file
|
||||
assert_select 'input#user_name[type=file]'
|
||||
end
|
||||
|
||||
test 'input should generate a country select field' do
|
||||
with_input_for @user, :country, :country
|
||||
assert_select 'select#user_country'
|
||||
assert_select 'select option[value=Brazil]', 'Brazil'
|
||||
assert_no_select 'select option[value=][disabled=disabled]'
|
||||
end
|
||||
|
||||
test 'input should generate a country select with simple form default' do
|
||||
swap SimpleForm, :country_priority => [ 'Brazil' ] do
|
||||
with_input_for @user, :country, :country
|
||||
assert_select 'select option[value=][disabled=disabled]'
|
||||
end
|
||||
end
|
||||
|
||||
test 'input should generate a time zone select field' do
|
||||
with_input_for @user, :time_zone, :time_zone
|
||||
assert_select 'select#user_time_zone'
|
||||
assert_select 'select option[value=Brasilia]', '(GMT-03:00) Brasilia'
|
||||
assert_no_select 'select option[value=][disabled=disabled]'
|
||||
end
|
||||
|
||||
test 'input should generate a time zone select field with default' do
|
||||
with_input_for @user, :time_zone, :time_zone, :default => 'Brasilia'
|
||||
assert_select 'select option[value=Brasilia][selected=selected]'
|
||||
end
|
||||
|
||||
test 'input should generate a time zone select using options priority' do
|
||||
with_input_for @user, :time_zone, :time_zone, :priority => /Brasilia/
|
||||
assert_select 'select option[value=][disabled=disabled]'
|
||||
end
|
||||
|
||||
test 'input should generate a datetime select by default for datetime attributes' do
|
||||
with_input_for @user, :created_at, :datetime
|
||||
1.upto(5) do |i|
|
||||
assert_select "form select.datetime#user_created_at_#{i}i"
|
||||
end
|
||||
end
|
||||
|
||||
test 'input should be able to pass options to datetime select' do
|
||||
with_input_for @user, :created_at, :datetime,
|
||||
:disabled => true, :prompt => { :year => 'ano', :month => 'mês', :day => 'dia' }
|
||||
|
||||
assert_select 'select.datetime[disabled=disabled]'
|
||||
assert_select 'select.datetime option', 'ano'
|
||||
assert_select 'select.datetime option', 'mês'
|
||||
assert_select 'select.datetime option', 'dia'
|
||||
end
|
||||
|
||||
test 'input should generate a date select for date attributes' do
|
||||
with_input_for @user, :born_at, :date
|
||||
assert_select 'select.date#user_born_at_1i'
|
||||
assert_select 'select.date#user_born_at_2i'
|
||||
assert_select 'select.date#user_born_at_3i'
|
||||
assert_no_select 'select.date#user_born_at_4i'
|
||||
end
|
||||
|
||||
test 'input should be able to pass options to date select' do
|
||||
with_input_for @user, :born_at, :date, :as => :date,
|
||||
:disabled => true, :prompt => { :year => 'ano', :month => 'mês', :day => 'dia' }
|
||||
|
||||
assert_select 'select.date[disabled=disabled]'
|
||||
assert_select 'select.date option', 'ano'
|
||||
assert_select 'select.date option', 'mês'
|
||||
assert_select 'select.date option', 'dia'
|
||||
end
|
||||
|
||||
test 'input should generate a time select for time attributes' do
|
||||
with_input_for @user, :delivery_time, :time
|
||||
assert_select 'input[type=hidden]#user_delivery_time_1i'
|
||||
assert_select 'input[type=hidden]#user_delivery_time_2i'
|
||||
assert_select 'input[type=hidden]#user_delivery_time_3i'
|
||||
assert_select 'select.time#user_delivery_time_4i'
|
||||
assert_select 'select.time#user_delivery_time_5i'
|
||||
end
|
||||
|
||||
test 'input should be able to pass options to time select' do
|
||||
with_input_for @user, :delivery_time, :time, :required => true,
|
||||
:disabled => true, :prompt => { :hour => 'hora', :minute => 'minuto' }
|
||||
|
||||
assert_select 'select.time[disabled=disabled]'
|
||||
assert_select 'select.time option', 'hora'
|
||||
assert_select 'select.time option', 'minuto'
|
||||
end
|
||||
|
||||
test 'input should generate boolean radio buttons by default for radio types' do
|
||||
with_input_for @user, :active, :radio
|
||||
assert_select 'input[type=radio][value=true].radio#user_active_true'
|
||||
assert_select 'input[type=radio][value=false].radio#user_active_false'
|
||||
end
|
||||
|
||||
test 'input as radio should generate internal labels by default' do
|
||||
with_input_for @user, :active, :radio
|
||||
assert_select 'label[for=user_active_true]', 'Yes'
|
||||
assert_select 'label[for=user_active_false]', 'No'
|
||||
end
|
||||
|
||||
test 'input as radio should use i18n to translate internal labels' do
|
||||
store_translations(:en, :simple_form => { :yes => 'Sim', :no => 'Não' }) do
|
||||
with_input_for @user, :active, :radio
|
||||
assert_select 'label[for=user_active_true]', 'Sim'
|
||||
assert_select 'label[for=user_active_false]', 'Não'
|
||||
end
|
||||
end
|
||||
|
||||
test 'input should generate a boolean select with options by default for select types' do
|
||||
with_input_for @user, :active, :select
|
||||
assert_select 'select.select#user_active'
|
||||
assert_select 'select option[value=true]', 'Yes'
|
||||
assert_select 'select option[value=false]', 'No'
|
||||
end
|
||||
|
||||
test 'input as select should use i18n to translate select boolean options' do
|
||||
store_translations(:en, :simple_form => { :yes => 'Sim', :no => 'Não' }) do
|
||||
with_input_for @user, :active, :select
|
||||
assert_select 'select option[value=true]', 'Sim'
|
||||
assert_select 'select option[value=false]', 'Não'
|
||||
end
|
||||
end
|
||||
|
||||
test 'input should allow overriding collection for select types' do
|
||||
with_input_for @user, :name, :select, :collection => ['Jose', 'Carlos']
|
||||
assert_select 'select.select#user_name'
|
||||
assert_select 'select option', 'Jose'
|
||||
assert_select 'select option', 'Carlos'
|
||||
end
|
||||
|
||||
test 'input should mark the selected value by default' do
|
||||
@user.name = "Carlos"
|
||||
with_input_for @user, :name, :select, :collection => ['Jose', 'Carlos']
|
||||
assert_select 'select option[selected=selected]', 'Carlos'
|
||||
end
|
||||
|
||||
test 'input should mark the selected value also when using integers' do
|
||||
@user.age = 18
|
||||
with_input_for @user, :age, :select, :collection => 18..60
|
||||
assert_select 'select option[selected=selected]', '18'
|
||||
end
|
||||
|
||||
test 'input should automatically set include blank' do
|
||||
with_input_for @user, :age, :select, :collection => 18..30
|
||||
assert_select 'select option[value=]', ''
|
||||
end
|
||||
|
||||
test 'input should not set include blank if otherwise is told' do
|
||||
with_input_for @user, :age, :select, :collection => 18..30, :include_blank => false
|
||||
assert_no_select 'select option[value=]', ''
|
||||
end
|
||||
|
||||
test 'input should not set include blank if prompt is given' do
|
||||
with_input_for @user, :age, :select, :collection => 18..30, :prompt => "Please select foo"
|
||||
assert_no_select 'select option[value=]', ''
|
||||
end
|
||||
|
||||
test 'input should not set include blank if multiple is given' do
|
||||
with_input_for @user, :age, :select, :collection => 18..30, :input_html => { :multiple => true }
|
||||
assert_no_select 'select option[value=]', ''
|
||||
end
|
||||
|
||||
test 'input should detect label and value on collections' do
|
||||
users = [ setup_new_user(:id => 1, :name => "Jose"), setup_new_user(:id => 2, :name => "Carlos") ]
|
||||
with_input_for @user, :description, :select, :collection => users
|
||||
assert_select 'select option[value=1]', 'Jose'
|
||||
assert_select 'select option[value=2]', 'Carlos'
|
||||
end
|
||||
|
||||
test 'input should allow overriding collection for radio types' do
|
||||
with_input_for @user, :name, :radio, :collection => ['Jose', 'Carlos']
|
||||
assert_select 'input[type=radio][value=Jose]'
|
||||
assert_select 'input[type=radio][value=Carlos]'
|
||||
assert_select 'label.collection_radio', 'Jose'
|
||||
assert_select 'label.collection_radio', 'Carlos'
|
||||
end
|
||||
|
||||
test 'input should mark the current radio value by default' do
|
||||
@user.name = "Carlos"
|
||||
with_input_for @user, :name, :radio, :collection => ['Jose', 'Carlos']
|
||||
assert_select 'input[type=radio][value=Carlos][checked=checked]'
|
||||
end
|
||||
|
||||
test 'input should allow using a collection with text/value arrays' do
|
||||
with_input_for @user, :name, :radio, :collection => [['Jose', 'jose'], ['Carlos', 'carlos']]
|
||||
assert_select 'input[type=radio][value=jose]'
|
||||
assert_select 'input[type=radio][value=carlos]'
|
||||
assert_select 'label.collection_radio', 'Jose'
|
||||
assert_select 'label.collection_radio', 'Carlos'
|
||||
end
|
||||
|
||||
test 'input should allow overriding label and value method for collections' do
|
||||
with_input_for @user, :name, :radio,
|
||||
:collection => ['Jose' , 'Carlos'],
|
||||
:label_method => :upcase,
|
||||
:value_method => :downcase
|
||||
assert_select 'input[type=radio][value=jose]'
|
||||
assert_select 'input[type=radio][value=carlos]'
|
||||
assert_select 'label.collection_radio', 'JOSE'
|
||||
assert_select 'label.collection_radio', 'CARLOS'
|
||||
end
|
||||
|
||||
test 'input should be required by default' do
|
||||
with_input_for @user, :name, :string
|
||||
assert_select 'input.required#user_name'
|
||||
end
|
||||
|
||||
test 'input should allow disabling required' do
|
||||
with_input_for @user, :name, :string, :required => false
|
||||
assert_no_select 'input.required'
|
||||
assert_select 'input.optional#user_name'
|
||||
end
|
||||
|
||||
test 'input should get options from column definition for string attributes' do
|
||||
with_input_for @user, :name, :string
|
||||
assert_select 'input.string[maxlength=100]'
|
||||
end
|
||||
|
||||
test 'input should get options from column definition for decimal attributes' do
|
||||
with_input_for @user, :credit_limit, :decimal
|
||||
assert_select 'input.decimal[maxlength=15]'
|
||||
end
|
||||
|
||||
test 'input should get options from column definition for password attributes' do
|
||||
with_input_for @user, :password, :password
|
||||
assert_select 'input.password[maxlength=100]'
|
||||
end
|
||||
|
||||
test 'input should not generate options for different attributes' do
|
||||
with_input_for @user, :description, :text
|
||||
assert_select 'textarea'
|
||||
assert_no_select 'textarea[maxlength]'
|
||||
end
|
||||
|
||||
test 'input should be generated properly when object is not present' do
|
||||
with_input_for :project, :name, :string
|
||||
assert_select 'input.string.required#project_name'
|
||||
end
|
||||
|
||||
test 'input as radio should be generated properly when object is not present ' do
|
||||
with_input_for :project, :name, :radio
|
||||
assert_select 'input.radio#project_name_true'
|
||||
assert_select 'input.radio#project_name_false'
|
||||
end
|
||||
|
||||
test 'input as select with collection should be generated properly when object is not present' do
|
||||
with_input_for :project, :name, :select, :collection => ['Jose', 'Carlos']
|
||||
assert_select 'select.select#project_name'
|
||||
end
|
||||
#
|
||||
# def with_input_for(object, attribute_name, type, options={})
|
||||
# simple_form_for object do |f|
|
||||
# f.attribute_name = attribute_name
|
||||
# f.column = object.column_for_attribute(attribute_name) if object.respond_to?(:column_for_attribute)
|
||||
# f.input_type = type
|
||||
# f.options = options
|
||||
#
|
||||
# input = SimpleForm::Components::Input.new(f, SimpleForm::FormBuilder::TERMINATOR)
|
||||
# concat(input.call)
|
||||
# yield input if block_given?
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# test 'input should map text field to string attribute' do
|
||||
# with_input_for @user, :name, :string
|
||||
# assert_select 'input[name=\'user[name]\'][id=user_name][value=New in Simple Form!]'
|
||||
# end
|
||||
#
|
||||
# test 'input should generate css class based on default input type' do
|
||||
# with_input_for @user, :name, :string
|
||||
# assert_select 'input.string'
|
||||
# with_input_for @user, :description, :text
|
||||
# assert_select 'textarea.text'
|
||||
# with_input_for @user, :age, :integer
|
||||
# assert_select 'input.integer'
|
||||
# with_input_for @user, :born_at, :date
|
||||
# assert_select 'select.date'
|
||||
# with_input_for @user, :created_at, :datetime
|
||||
# assert_select 'select.datetime'
|
||||
# end
|
||||
#
|
||||
# test 'input should allow passing options to text field' do
|
||||
# with_input_for @user, :name, :string, :input_html => { :class => 'my_input', :id => 'my_input' }
|
||||
# assert_select 'input#my_input.my_input'
|
||||
# end
|
||||
#
|
||||
# test 'input should generate a text area for text attributes' do
|
||||
# with_input_for @user, :description, :text
|
||||
# assert_select 'textarea.text#user_description'
|
||||
# end
|
||||
#
|
||||
# test 'input should generate an integer text field for integer attributes ' do
|
||||
# with_input_for @user, :age, :integer
|
||||
# assert_select 'input.integer#user_age'
|
||||
# end
|
||||
#
|
||||
# test 'input should generate a float text field for float attributes ' do
|
||||
# with_input_for @user, :age, :float
|
||||
# assert_select 'input.float#user_age'
|
||||
# end
|
||||
#
|
||||
# test 'input should generate a decimal text field for decimal attributes ' do
|
||||
# with_input_for @user, :age, :decimal
|
||||
# assert_select 'input.decimal#user_age'
|
||||
# end
|
||||
#
|
||||
# test 'input should generate a checkbox by default for boolean attributes' do
|
||||
# with_input_for @user, :active, :boolean
|
||||
# assert_select 'input[type=checkbox].boolean#user_active'
|
||||
# end
|
||||
#
|
||||
# test 'input should generate a password field for password attributes' do
|
||||
# with_input_for @user, :password, :password
|
||||
# assert_select 'input[type=password].password#user_password'
|
||||
# end
|
||||
#
|
||||
# test 'input should generate a hidden field' do
|
||||
# with_input_for @user, :name, :hidden
|
||||
# assert_no_select 'input[type=text]'
|
||||
# assert_select 'input#user_name[type=hidden]'
|
||||
# end
|
||||
#
|
||||
# test 'input should generate a file field' do
|
||||
# with_input_for @user, :name, :file
|
||||
# assert_select 'input#user_name[type=file]'
|
||||
# end
|
||||
#
|
||||
# test 'input should generate a country select field' do
|
||||
# with_input_for @user, :country, :country
|
||||
# assert_select 'select#user_country'
|
||||
# assert_select 'select option[value=Brazil]', 'Brazil'
|
||||
# assert_no_select 'select option[value=][disabled=disabled]'
|
||||
# end
|
||||
#
|
||||
# test 'input should generate a country select with simple form default' do
|
||||
# swap SimpleForm, :country_priority => [ 'Brazil' ] do
|
||||
# with_input_for @user, :country, :country
|
||||
# assert_select 'select option[value=][disabled=disabled]'
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# test 'input should generate a time zone select field' do
|
||||
# with_input_for @user, :time_zone, :time_zone
|
||||
# assert_select 'select#user_time_zone'
|
||||
# assert_select 'select option[value=Brasilia]', '(GMT-03:00) Brasilia'
|
||||
# assert_no_select 'select option[value=][disabled=disabled]'
|
||||
# end
|
||||
#
|
||||
# test 'input should generate a time zone select field with default' do
|
||||
# with_input_for @user, :time_zone, :time_zone, :default => 'Brasilia'
|
||||
# assert_select 'select option[value=Brasilia][selected=selected]'
|
||||
# end
|
||||
#
|
||||
# test 'input should generate a time zone select using options priority' do
|
||||
# with_input_for @user, :time_zone, :time_zone, :priority => /Brasilia/
|
||||
# assert_select 'select option[value=][disabled=disabled]'
|
||||
# end
|
||||
#
|
||||
# test 'input should generate a datetime select by default for datetime attributes' do
|
||||
# with_input_for @user, :created_at, :datetime
|
||||
# 1.upto(5) do |i|
|
||||
# assert_select "form select.datetime#user_created_at_#{i}i"
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# test 'input should be able to pass options to datetime select' do
|
||||
# with_input_for @user, :created_at, :datetime,
|
||||
# :disabled => true, :prompt => { :year => 'ano', :month => 'mês', :day => 'dia' }
|
||||
#
|
||||
# assert_select 'select.datetime[disabled=disabled]'
|
||||
# assert_select 'select.datetime option', 'ano'
|
||||
# assert_select 'select.datetime option', 'mês'
|
||||
# assert_select 'select.datetime option', 'dia'
|
||||
# end
|
||||
#
|
||||
# test 'input should generate a date select for date attributes' do
|
||||
# with_input_for @user, :born_at, :date
|
||||
# assert_select 'select.date#user_born_at_1i'
|
||||
# assert_select 'select.date#user_born_at_2i'
|
||||
# assert_select 'select.date#user_born_at_3i'
|
||||
# assert_no_select 'select.date#user_born_at_4i'
|
||||
# end
|
||||
#
|
||||
# test 'input should be able to pass options to date select' do
|
||||
# with_input_for @user, :born_at, :date, :as => :date,
|
||||
# :disabled => true, :prompt => { :year => 'ano', :month => 'mês', :day => 'dia' }
|
||||
#
|
||||
# assert_select 'select.date[disabled=disabled]'
|
||||
# assert_select 'select.date option', 'ano'
|
||||
# assert_select 'select.date option', 'mês'
|
||||
# assert_select 'select.date option', 'dia'
|
||||
# end
|
||||
#
|
||||
# test 'input should generate a time select for time attributes' do
|
||||
# with_input_for @user, :delivery_time, :time
|
||||
# assert_select 'input[type=hidden]#user_delivery_time_1i'
|
||||
# assert_select 'input[type=hidden]#user_delivery_time_2i'
|
||||
# assert_select 'input[type=hidden]#user_delivery_time_3i'
|
||||
# assert_select 'select.time#user_delivery_time_4i'
|
||||
# assert_select 'select.time#user_delivery_time_5i'
|
||||
# end
|
||||
#
|
||||
# test 'input should be able to pass options to time select' do
|
||||
# with_input_for @user, :delivery_time, :time, :required => true,
|
||||
# :disabled => true, :prompt => { :hour => 'hora', :minute => 'minuto' }
|
||||
#
|
||||
# assert_select 'select.time[disabled=disabled]'
|
||||
# assert_select 'select.time option', 'hora'
|
||||
# assert_select 'select.time option', 'minuto'
|
||||
# end
|
||||
#
|
||||
# test 'input should generate boolean radio buttons by default for radio types' do
|
||||
# with_input_for @user, :active, :radio
|
||||
# assert_select 'input[type=radio][value=true].radio#user_active_true'
|
||||
# assert_select 'input[type=radio][value=false].radio#user_active_false'
|
||||
# end
|
||||
#
|
||||
# test 'input as radio should generate internal labels by default' do
|
||||
# with_input_for @user, :active, :radio
|
||||
# assert_select 'label[for=user_active_true]', 'Yes'
|
||||
# assert_select 'label[for=user_active_false]', 'No'
|
||||
# end
|
||||
#
|
||||
# test 'input as radio should use i18n to translate internal labels' do
|
||||
# store_translations(:en, :simple_form => { :yes => 'Sim', :no => 'Não' }) do
|
||||
# with_input_for @user, :active, :radio
|
||||
# assert_select 'label[for=user_active_true]', 'Sim'
|
||||
# assert_select 'label[for=user_active_false]', 'Não'
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# test 'input should generate a boolean select with options by default for select types' do
|
||||
# with_input_for @user, :active, :select
|
||||
# assert_select 'select.select#user_active'
|
||||
# assert_select 'select option[value=true]', 'Yes'
|
||||
# assert_select 'select option[value=false]', 'No'
|
||||
# end
|
||||
#
|
||||
# test 'input as select should use i18n to translate select boolean options' do
|
||||
# store_translations(:en, :simple_form => { :yes => 'Sim', :no => 'Não' }) do
|
||||
# with_input_for @user, :active, :select
|
||||
# assert_select 'select option[value=true]', 'Sim'
|
||||
# assert_select 'select option[value=false]', 'Não'
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# test 'input should allow overriding collection for select types' do
|
||||
# with_input_for @user, :name, :select, :collection => ['Jose', 'Carlos']
|
||||
# assert_select 'select.select#user_name'
|
||||
# assert_select 'select option', 'Jose'
|
||||
# assert_select 'select option', 'Carlos'
|
||||
# end
|
||||
#
|
||||
# test 'input should mark the selected value by default' do
|
||||
# @user.name = "Carlos"
|
||||
# with_input_for @user, :name, :select, :collection => ['Jose', 'Carlos']
|
||||
# assert_select 'select option[selected=selected]', 'Carlos'
|
||||
# end
|
||||
#
|
||||
# test 'input should mark the selected value also when using integers' do
|
||||
# @user.age = 18
|
||||
# with_input_for @user, :age, :select, :collection => 18..60
|
||||
# assert_select 'select option[selected=selected]', '18'
|
||||
# end
|
||||
#
|
||||
# test 'input should automatically set include blank' do
|
||||
# with_input_for @user, :age, :select, :collection => 18..30
|
||||
# assert_select 'select option[value=]', ''
|
||||
# end
|
||||
#
|
||||
# test 'input should not set include blank if otherwise is told' do
|
||||
# with_input_for @user, :age, :select, :collection => 18..30, :include_blank => false
|
||||
# assert_no_select 'select option[value=]', ''
|
||||
# end
|
||||
#
|
||||
# test 'input should not set include blank if prompt is given' do
|
||||
# with_input_for @user, :age, :select, :collection => 18..30, :prompt => "Please select foo"
|
||||
# assert_no_select 'select option[value=]', ''
|
||||
# end
|
||||
#
|
||||
# test 'input should not set include blank if multiple is given' do
|
||||
# with_input_for @user, :age, :select, :collection => 18..30, :input_html => { :multiple => true }
|
||||
# assert_no_select 'select option[value=]', ''
|
||||
# end
|
||||
#
|
||||
# test 'input should detect label and value on collections' do
|
||||
# users = [ setup_new_user(:id => 1, :name => "Jose"), setup_new_user(:id => 2, :name => "Carlos") ]
|
||||
# with_input_for @user, :description, :select, :collection => users
|
||||
# assert_select 'select option[value=1]', 'Jose'
|
||||
# assert_select 'select option[value=2]', 'Carlos'
|
||||
# end
|
||||
#
|
||||
# test 'input should allow overriding collection for radio types' do
|
||||
# with_input_for @user, :name, :radio, :collection => ['Jose', 'Carlos']
|
||||
# assert_select 'input[type=radio][value=Jose]'
|
||||
# assert_select 'input[type=radio][value=Carlos]'
|
||||
# assert_select 'label.collection_radio', 'Jose'
|
||||
# assert_select 'label.collection_radio', 'Carlos'
|
||||
# end
|
||||
#
|
||||
# test 'input should mark the current radio value by default' do
|
||||
# @user.name = "Carlos"
|
||||
# with_input_for @user, :name, :radio, :collection => ['Jose', 'Carlos']
|
||||
# assert_select 'input[type=radio][value=Carlos][checked=checked]'
|
||||
# end
|
||||
#
|
||||
# test 'input should allow using a collection with text/value arrays' do
|
||||
# with_input_for @user, :name, :radio, :collection => [['Jose', 'jose'], ['Carlos', 'carlos']]
|
||||
# assert_select 'input[type=radio][value=jose]'
|
||||
# assert_select 'input[type=radio][value=carlos]'
|
||||
# assert_select 'label.collection_radio', 'Jose'
|
||||
# assert_select 'label.collection_radio', 'Carlos'
|
||||
# end
|
||||
#
|
||||
# test 'input should allow overriding label and value method for collections' do
|
||||
# with_input_for @user, :name, :radio,
|
||||
# :collection => ['Jose' , 'Carlos'],
|
||||
# :label_method => :upcase,
|
||||
# :value_method => :downcase
|
||||
# assert_select 'input[type=radio][value=jose]'
|
||||
# assert_select 'input[type=radio][value=carlos]'
|
||||
# assert_select 'label.collection_radio', 'JOSE'
|
||||
# assert_select 'label.collection_radio', 'CARLOS'
|
||||
# end
|
||||
#
|
||||
# test 'input should be required by default' do
|
||||
# with_input_for @user, :name, :string
|
||||
# assert_select 'input.required#user_name'
|
||||
# end
|
||||
#
|
||||
# test 'input should allow disabling required' do
|
||||
# with_input_for @user, :name, :string, :required => false
|
||||
# assert_no_select 'input.required'
|
||||
# assert_select 'input.optional#user_name'
|
||||
# end
|
||||
#
|
||||
# test 'input should get options from column definition for string attributes' do
|
||||
# with_input_for @user, :name, :string
|
||||
# assert_select 'input.string[maxlength=100]'
|
||||
# end
|
||||
#
|
||||
# test 'input should get options from column definition for decimal attributes' do
|
||||
# with_input_for @user, :credit_limit, :decimal
|
||||
# assert_select 'input.decimal[maxlength=15]'
|
||||
# end
|
||||
#
|
||||
# test 'input should get options from column definition for password attributes' do
|
||||
# with_input_for @user, :password, :password
|
||||
# assert_select 'input.password[maxlength=100]'
|
||||
# end
|
||||
#
|
||||
# test 'input should not generate options for different attributes' do
|
||||
# with_input_for @user, :description, :text
|
||||
# assert_select 'textarea'
|
||||
# assert_no_select 'textarea[maxlength]'
|
||||
# end
|
||||
#
|
||||
# test 'input should be generated properly when object is not present' do
|
||||
# with_input_for :project, :name, :string
|
||||
# assert_select 'input.string.required#project_name'
|
||||
# end
|
||||
#
|
||||
# test 'input as radio should be generated properly when object is not present ' do
|
||||
# with_input_for :project, :name, :radio
|
||||
# assert_select 'input.radio#project_name_true'
|
||||
# assert_select 'input.radio#project_name_false'
|
||||
# end
|
||||
#
|
||||
# test 'input as select with collection should be generated properly when object is not present' do
|
||||
# with_input_for :project, :name, :select, :collection => ['Jose', 'Carlos']
|
||||
# assert_select 'select.select#project_name'
|
||||
# end
|
||||
end
|
||||
|
|
|
@ -3,7 +3,7 @@ require 'test_helper'
|
|||
class LabelTest < ActionView::TestCase
|
||||
|
||||
setup do
|
||||
SimpleForm::FormBuilder::Base.reset_i18n_cache :translate_required_html
|
||||
SimpleForm::Inputs::Base.reset_i18n_cache :translate_required_html
|
||||
end
|
||||
|
||||
def with_label_for(object, attribute_name, type, options={})
|
||||
|
@ -13,7 +13,7 @@ class LabelTest < ActionView::TestCase
|
|||
f.input_type = type
|
||||
f.options = options
|
||||
|
||||
concat(SimpleForm::FormBuilder::Base.new(f).label)
|
||||
concat(SimpleForm::Inputs::Base.new(f).label)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in New Issue