Refactor Inputs::Base into helpers and make :on based on the resource status.
This commit is contained in:
parent
5cdf47bf72
commit
a4655ba845
|
@ -2,7 +2,7 @@
|
|||
SimpleForm.setup do |config|
|
||||
# Components used by the form builder to generate a complete input. You can remove
|
||||
# any of them, change the order, or even add your own components to the stack.
|
||||
# config.components = [ :placeholder, :maxlength, :label_input, :hint, :error ]
|
||||
# config.components = [ :placeholder, :label_input, :hint, :error ]
|
||||
|
||||
# Default tag used on hints.
|
||||
# config.hint_tag = :span
|
||||
|
|
|
@ -7,6 +7,7 @@ module SimpleForm
|
|||
autoload :ErrorNotification, 'simple_form/error_notification'
|
||||
autoload :FormBuilder, 'simple_form/form_builder'
|
||||
autoload :HasErrors, 'simple_form/has_errors'
|
||||
autoload :Helpers, 'simple_form/helpers'
|
||||
autoload :I18nCache, 'simple_form/i18n_cache'
|
||||
autoload :Inputs, 'simple_form/inputs'
|
||||
autoload :MapType, 'simple_form/map_type'
|
||||
|
@ -45,7 +46,7 @@ module SimpleForm
|
|||
|
||||
# Components used by the form builder.
|
||||
mattr_accessor :components
|
||||
@@components = [ :placeholder, :maxlength, :label_input, :hint, :error ]
|
||||
@@components = [ :placeholder, :label_input, :hint, :error ]
|
||||
|
||||
# Series of attemps to detect a default label method for collection.
|
||||
mattr_accessor :collection_label_methods
|
||||
|
|
|
@ -6,6 +6,5 @@ module SimpleForm
|
|||
autoload :Labels, 'simple_form/components/labels'
|
||||
autoload :Placeholders, 'simple_form/components/placeholders'
|
||||
autoload :Wrapper, 'simple_form/components/wrapper'
|
||||
autoload :Maxlength, 'simple_form/components/maxlength'
|
||||
end
|
||||
end
|
||||
|
|
|
@ -2,8 +2,7 @@ module SimpleForm
|
|||
module Components
|
||||
module Placeholders
|
||||
def placeholder
|
||||
# This components is disabled by default.
|
||||
nil
|
||||
nil # This components is disabled by default.
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
module SimpleForm
|
||||
module Helpers
|
||||
autoload :Maxlength, 'simple_form/helpers/maxlength'
|
||||
autoload :Pattern, 'simple_form/helpers/pattern'
|
||||
autoload :Validators, 'simple_form/helpers/validators'
|
||||
autoload :Required, 'simple_form/helpers/required'
|
||||
end
|
||||
end
|
|
@ -1,18 +1,12 @@
|
|||
module SimpleForm
|
||||
module Components
|
||||
module Maxlength
|
||||
def maxlength
|
||||
# This components is disabled by default.
|
||||
nil
|
||||
end
|
||||
module Helpers
|
||||
# Helper methods for maxlength.
|
||||
module Maxlength #:nodoc:
|
||||
|
||||
private
|
||||
|
||||
def active_maxlength
|
||||
if SimpleForm.html5
|
||||
input_html_options[:maxlength] ||= maximum_length_from_validation || limit
|
||||
end
|
||||
nil
|
||||
def add_maxlength!
|
||||
input_html_options[:maxlength] ||= maximum_length_from_validation || limit if SimpleForm.html5
|
||||
end
|
||||
|
||||
def maximum_length_from_validation
|
|
@ -0,0 +1,25 @@
|
|||
module SimpleForm
|
||||
module Helpers
|
||||
# Helper methods for pattern.
|
||||
module Pattern #:nodoc:
|
||||
private
|
||||
|
||||
def add_pattern!
|
||||
input_html_options[:pattern] ||= pattern_source if validate_pattern?
|
||||
end
|
||||
|
||||
def validate_pattern?
|
||||
has_validators? && SimpleForm.html5 &&
|
||||
SimpleForm.browser_validations && pattern_validator.present?
|
||||
end
|
||||
|
||||
def pattern_source
|
||||
pattern_validator.options[:with].source
|
||||
end
|
||||
|
||||
def pattern_validator
|
||||
@pattern_validator ||= attribute_validators.find { |v| ActiveModel::Validations::FormatValidator === v }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,36 @@
|
|||
module SimpleForm
|
||||
module Helpers
|
||||
module Required
|
||||
private
|
||||
|
||||
def attribute_required?
|
||||
@required
|
||||
end
|
||||
|
||||
def calculate_required
|
||||
if !options[:required].nil?
|
||||
options[:required]
|
||||
elsif has_validators?
|
||||
(attribute_validators + reflection_validators).any? do |v|
|
||||
v.kind == :presence && valid_validator?(v)
|
||||
end
|
||||
else
|
||||
attribute_required_by_default?
|
||||
end
|
||||
end
|
||||
|
||||
# Whether this input is valid for HTML 5 required attribute.
|
||||
def has_required?
|
||||
attribute_required? && SimpleForm.html5 && SimpleForm.browser_validations
|
||||
end
|
||||
|
||||
def attribute_required_by_default?
|
||||
SimpleForm.required_by_default
|
||||
end
|
||||
|
||||
def required_class
|
||||
attribute_required? ? :required : :optional
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,40 @@
|
|||
module SimpleForm
|
||||
module Helpers
|
||||
module Validators
|
||||
private
|
||||
|
||||
def has_validators?
|
||||
attribute_name && object.class.respond_to?(:validators_on)
|
||||
end
|
||||
|
||||
def attribute_validators
|
||||
object.class.validators_on(attribute_name)
|
||||
end
|
||||
|
||||
def reflection_validators
|
||||
reflection ? object.class.validators_on(reflection.name) : []
|
||||
end
|
||||
|
||||
def valid_validator?(validator)
|
||||
!conditional_validators?(validator) && action_validator_match?(validator)
|
||||
end
|
||||
|
||||
def conditional_validators?(validator)
|
||||
validator.options.include?(:if) || validator.options.include?(:unless)
|
||||
end
|
||||
|
||||
def action_validator_match?(validator)
|
||||
return true if !validator.options.include?(:on)
|
||||
|
||||
case validator.options[:on]
|
||||
when :save
|
||||
true
|
||||
when :create
|
||||
!object.persisted?
|
||||
when :update
|
||||
object.persisted?
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -9,12 +9,16 @@ module SimpleForm
|
|||
:update => :edit
|
||||
}
|
||||
|
||||
include SimpleForm::Helpers::Required
|
||||
include SimpleForm::Helpers::Validators
|
||||
include SimpleForm::Helpers::Maxlength
|
||||
include SimpleForm::Helpers::Pattern
|
||||
|
||||
include SimpleForm::Components::Errors
|
||||
include SimpleForm::Components::Hints
|
||||
include SimpleForm::Components::LabelInput
|
||||
include SimpleForm::Components::Placeholders
|
||||
include SimpleForm::Components::Wrapper
|
||||
include SimpleForm::Components::Maxlength
|
||||
|
||||
# Enables certain components support to the given input.
|
||||
def self.enable(*args)
|
||||
|
@ -63,7 +67,11 @@ module SimpleForm
|
|||
wrap(content)
|
||||
end
|
||||
|
||||
protected
|
||||
private
|
||||
|
||||
def add_size!
|
||||
input_html_options[:size] ||= [limit, SimpleForm.default_input_size].compact.min
|
||||
end
|
||||
|
||||
def limit
|
||||
column && column.limit
|
||||
|
@ -73,59 +81,10 @@ module SimpleForm
|
|||
options[:components] || SimpleForm.components
|
||||
end
|
||||
|
||||
def attribute_required?
|
||||
@required
|
||||
end
|
||||
|
||||
def calculate_required
|
||||
if !options[:required].nil?
|
||||
options[:required]
|
||||
elsif has_validators?
|
||||
(attribute_validators + reflection_validators).any? do |v|
|
||||
v.kind == :presence && !conditional_validators?(v) && action_validators?(v)
|
||||
end
|
||||
else
|
||||
attribute_required_by_default?
|
||||
end
|
||||
end
|
||||
|
||||
# Whether this input is valid for HTML 5 required attribute.
|
||||
def has_required?
|
||||
attribute_required? && SimpleForm.html5 && SimpleForm.browser_validations
|
||||
end
|
||||
|
||||
def has_autofocus?
|
||||
options[:autofocus]
|
||||
end
|
||||
|
||||
def has_validators?
|
||||
attribute_name && object.class.respond_to?(:validators_on)
|
||||
end
|
||||
|
||||
def attribute_validators
|
||||
object.class.validators_on(attribute_name)
|
||||
end
|
||||
|
||||
def reflection_validators
|
||||
reflection ? object.class.validators_on(reflection.name) : []
|
||||
end
|
||||
|
||||
def conditional_validators?(validator)
|
||||
validator.options.include?(:if) || validator.options.include?(:unless)
|
||||
end
|
||||
|
||||
def action_validators?(validator)
|
||||
!validator.options.include?(:on) || ACTIONS[validator.options[:on].to_sym] == lookup_action
|
||||
end
|
||||
|
||||
def attribute_required_by_default?
|
||||
SimpleForm.required_by_default
|
||||
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
|
||||
|
@ -216,11 +175,6 @@ module SimpleForm
|
|||
action = action.to_sym
|
||||
ACTIONS[action] || action
|
||||
end
|
||||
|
||||
def input_method
|
||||
self.class.mappings[input_type] or
|
||||
raise("Could not find method for #{input_type.inspect}")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
module SimpleForm
|
||||
module Inputs
|
||||
class PasswordInput < Base
|
||||
enable :maxlength, :placeholder
|
||||
enable :placeholder
|
||||
|
||||
def input
|
||||
input_html_options[:size] ||= [limit, SimpleForm.default_input_size].compact.min
|
||||
add_size!
|
||||
add_maxlength!
|
||||
@builder.password_field(attribute_name, input_html_options)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
module SimpleForm
|
||||
module Inputs
|
||||
class StringInput < Base
|
||||
enable :maxlength, :placeholder
|
||||
enable :placeholder
|
||||
|
||||
def input
|
||||
input_html_options[:size] ||= [limit, SimpleForm.default_input_size].compact.min
|
||||
input_html_options[:pattern] ||= pattern_validator if validate_pattern?
|
||||
input_html_options[:type] ||= input_type if SimpleForm.html5 && !string?
|
||||
input_html_options[:type] ||= input_type if SimpleForm.html5 && !string?
|
||||
add_maxlength!
|
||||
add_pattern!
|
||||
add_size!
|
||||
@builder.text_field(attribute_name, input_html_options)
|
||||
end
|
||||
|
||||
|
@ -14,24 +15,11 @@ module SimpleForm
|
|||
string? ? super : super.unshift("string")
|
||||
end
|
||||
|
||||
protected
|
||||
private
|
||||
|
||||
def string?
|
||||
input_type == :string
|
||||
end
|
||||
|
||||
def validate_pattern?
|
||||
return unless has_validators?
|
||||
SimpleForm.html5 && SimpleForm.browser_validations && find_pattern_validator.present?
|
||||
end
|
||||
|
||||
def pattern_validator
|
||||
find_pattern_validator.options[:with].source
|
||||
end
|
||||
|
||||
def find_pattern_validator
|
||||
attribute_validators.find { |v| ActiveModel::Validations::FormatValidator === v }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
module SimpleForm
|
||||
module Inputs
|
||||
class TextInput < Base
|
||||
enable :maxlength, :placeholder
|
||||
enable :placeholder
|
||||
|
||||
def input
|
||||
add_maxlength!
|
||||
@builder.text_area(attribute_name, input_html_options)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -338,6 +338,8 @@ class FormBuilderTest < ActionView::TestCase
|
|||
assert_select 'input.optional#user_name'
|
||||
end
|
||||
|
||||
# VALIDATORS :if :unless
|
||||
|
||||
test 'builder input should not be required when ActiveModel::Validations is included and if option is present' do
|
||||
with_form_for @validating_user, :age
|
||||
assert_no_select 'input.required'
|
||||
|
@ -345,22 +347,6 @@ class FormBuilderTest < ActionView::TestCase
|
|||
assert_select 'input.optional#validating_user_age'
|
||||
end
|
||||
|
||||
test 'builder input should be required when validation is on create' do
|
||||
@controller.action_name = "new"
|
||||
with_form_for @validating_user, :action
|
||||
assert_select 'input.required'
|
||||
assert_select 'input[required]'
|
||||
assert_select 'input.required[required]#validating_user_action'
|
||||
end
|
||||
|
||||
test 'builder input should not be required when validation is on other action' do
|
||||
@controller.action_name = "edit"
|
||||
with_form_for @validating_user, :action
|
||||
assert_no_select 'input.required'
|
||||
assert_no_select 'input[required]'
|
||||
assert_select 'input.optional#validating_user_action'
|
||||
end
|
||||
|
||||
test 'builder input should not be required when ActiveModel::Validations is included and unless option is present' do
|
||||
with_form_for @validating_user, :amount
|
||||
assert_no_select 'input.required'
|
||||
|
@ -368,7 +354,53 @@ class FormBuilderTest < ActionView::TestCase
|
|||
assert_select 'input.optional#validating_user_amount'
|
||||
end
|
||||
|
||||
# VALIDATORS :on
|
||||
|
||||
test 'builder input should be required when validation is on create and is not persisted' do
|
||||
@validating_user.new_record!
|
||||
with_form_for @validating_user, :action
|
||||
assert_select 'input.required'
|
||||
assert_select 'input[required]'
|
||||
assert_select 'input.required[required]#validating_user_action'
|
||||
end
|
||||
|
||||
test 'builder input should not be required when validation is on create and is persisted' do
|
||||
with_form_for @validating_user, :action
|
||||
assert_no_select 'input.required'
|
||||
assert_no_select 'input[required]'
|
||||
assert_select 'input.optional#validating_user_action'
|
||||
end
|
||||
|
||||
test 'builder input should be required when validation is on save' do
|
||||
with_form_for @validating_user, :credit_limit
|
||||
assert_select 'input.required'
|
||||
assert_select 'input[required]'
|
||||
assert_select 'input.required[required]#validating_user_credit_limit'
|
||||
|
||||
@validating_user.new_record!
|
||||
with_form_for @validating_user, :credit_limit
|
||||
assert_select 'input.required'
|
||||
assert_select 'input[required]'
|
||||
assert_select 'input.required[required]#validating_user_credit_limit'
|
||||
end
|
||||
|
||||
test 'builder input should be required when validation is on update and is persisted' do
|
||||
with_form_for @validating_user, :phone_number
|
||||
assert_select 'input.required'
|
||||
assert_select 'input[required]'
|
||||
assert_select 'input.required[required]#validating_user_phone_number'
|
||||
end
|
||||
|
||||
test 'builder input should not be required when validation is on update and is not persisted' do
|
||||
@validating_user.new_record!
|
||||
with_form_for @validating_user, :phone_number
|
||||
assert_no_select 'input.required'
|
||||
assert_no_select 'input[required]'
|
||||
assert_select 'input.optional#validating_user_phone_number'
|
||||
end
|
||||
|
||||
# WRAPPERS
|
||||
|
||||
test 'builder support wrapping around an specific tag' do
|
||||
swap SimpleForm, :wrapper_tag => :p do
|
||||
with_form_for @user, :name
|
||||
|
|
|
@ -130,7 +130,11 @@ class ValidatingUser < User
|
|||
validates :company, :presence => true
|
||||
validates :age, :presence => true, :if => Proc.new { |user| user.name }
|
||||
validates :amount, :presence => true, :unless => Proc.new { |user| user.age }
|
||||
validates :action, :presence => true, :on => :create
|
||||
|
||||
validates :action, :presence => true, :on => :create
|
||||
validates :credit_limit, :presence => true, :on => :save
|
||||
validates :phone_number, :presence => true, :on => :update
|
||||
|
||||
validates_numericality_of :age,
|
||||
:greater_than_or_equal_to => 18,
|
||||
:less_than_or_equal_to => 99,
|
||||
|
|
|
@ -89,5 +89,6 @@ class ActionView::TestCase
|
|||
alias :users_path :user_path
|
||||
alias :super_user_path :user_path
|
||||
alias :validating_user_path :user_path
|
||||
alias :validating_users_path :user_path
|
||||
alias :other_validating_user_path :user_path
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue