Skip to content

Commit

Permalink
Make min_max also a component.
Browse files Browse the repository at this point in the history
  • Loading branch information
josevalim committed Dec 4, 2011
1 parent d3ddd2a commit f883b20
Show file tree
Hide file tree
Showing 6 changed files with 65 additions and 54 deletions.
Expand Up @@ -10,14 +10,16 @@
b.use :html5

## Extensions
# Calculate maxlength from validations for string inputs
b.use :maxlength
# Automatically use translation to retrieve a placeholder
# Calculates maxlength from length validations automatically for string inputs
# b.use :maxlength
# Calculates pattern from format validations automatically for string inputs
# b.use :pattern
# Calculates min and max from length validations automatically for numeric inputs
# b.use :min_max
# Calculates placeholders automatically from I18n
b.use :placeholder
# Add the HTML5 required attribute to the input
# Calculates required from presence validations automatically
b.use :required
# Add a pattern from format validations for string inputs
b.use :pattern

## Inputs
b.use :label_input
Expand Down
1 change: 1 addition & 0 deletions lib/simple_form.rb
Expand Up @@ -144,6 +144,7 @@ def self.build(options={})
wrappers :class => :input, :error_class => :field_with_errors do |b|
b.use :html5

b.use :min_max
b.use :maxlength
b.use :placeholder
b.use :required
Expand Down
1 change: 1 addition & 0 deletions lib/simple_form/components.rb
Expand Up @@ -11,6 +11,7 @@ module Components
autoload :HTML5, 'simple_form/components/html5'
autoload :LabelInput, 'simple_form/components/label_input'
autoload :Labels, 'simple_form/components/labels'
autoload :MinMax, 'simple_form/components/min_max'
autoload :Maxlength, 'simple_form/components/maxlength'
autoload :Pattern, 'simple_form/components/pattern'
autoload :Placeholders, 'simple_form/components/placeholders'
Expand Down
51 changes: 51 additions & 0 deletions lib/simple_form/components/min_max.rb
@@ -0,0 +1,51 @@
module SimpleForm
module Components
module MinMax
def min_max
return unless has_validators?

if numeric_validator = find_numericality_validator
validator_options = numeric_validator.options
input_html_options[:min] ||= minimum_value(validator_options)
input_html_options[:max] ||= maximum_value(validator_options)
end
end

private

def integer?
input_type == :integer
end

def minimum_value(validator_options)
if integer? && validator_options.key?(:greater_than)
evaluate_validator_option(validator_options[:greater_than]) + 1
else
evaluate_validator_option(validator_options[:greater_than_or_equal_to])
end
end

def maximum_value(validator_options)
if integer? && validator_options.key?(:less_than)
evaluate_validator_option(validator_options[:less_than]) - 1
else
evaluate_validator_option(validator_options[:less_than_or_equal_to])
end
end

def find_numericality_validator
find_validator(ActiveModel::Validations::NumericalityValidator)
end

def evaluate_validator_option(option)
if option.is_a?(Numeric)
option
elsif option.is_a?(Symbol)
object.send(option)
elsif option.respond_to?(:call)
option.call(object)
end
end
end
end
end
5 changes: 3 additions & 2 deletions lib/simple_form/inputs/base.rb
Expand Up @@ -13,6 +13,7 @@ class Base
include SimpleForm::Components::Hints
include SimpleForm::Components::HTML5
include SimpleForm::Components::LabelInput
include SimpleForm::Components::MinMax
include SimpleForm::Components::Maxlength
include SimpleForm::Components::Pattern
include SimpleForm::Components::Placeholders
Expand Down Expand Up @@ -44,7 +45,7 @@ def self.ability(keys, value)
enable :hint

# Usually disabled, needs to be enabled explicitly passing true as option.
disable :maxlength, :placeholder, :pattern
disable :maxlength, :placeholder, :pattern, :min_max

def initialize(builder, attribute_name, column, input_type, options = {})
super
Expand All @@ -54,7 +55,7 @@ def initialize(builder, attribute_name, column, input_type, options = {})
@column = column
@input_type = input_type
@reflection = options.delete(:reflection)
@options = self.class.default_options.merge(options)
@options = options.reverse_merge!(self.class.default_options)
@required = calculate_required

# Notice that html_options_for receives a reference to input_html_classes.
Expand Down
47 changes: 1 addition & 46 deletions lib/simple_form/inputs/numeric_input.rb
@@ -1,15 +1,14 @@
module SimpleForm
module Inputs
class NumericInput < Base
enable :placeholder
enable :placeholder, :min_max

def input
add_size!
input_html_classes.unshift("numeric")
if html5?
input_html_options[:type] ||= "number"
input_html_options[:step] ||= integer? ? 1 : "any"
infer_attributes_from_validations!
end
@builder.text_field(attribute_name, input_html_options)
end
Expand All @@ -20,50 +19,6 @@ def input
def add_size!
input_html_options[:size] ||= nil
end

def infer_attributes_from_validations!
return unless has_validators?

if numeric_validator = find_numericality_validator
validator_options = numeric_validator.options
input_html_options[:min] ||= minimum_value(validator_options)
input_html_options[:max] ||= maximum_value(validator_options)
end
end

def integer?
input_type == :integer
end

def minimum_value(validator_options)
if integer? && validator_options.key?(:greater_than)
evaluate_validator_option(validator_options[:greater_than]) + 1
else
evaluate_validator_option(validator_options[:greater_than_or_equal_to])
end
end

def maximum_value(validator_options)
if integer? && validator_options.key?(:less_than)
evaluate_validator_option(validator_options[:less_than]) - 1
else
evaluate_validator_option(validator_options[:less_than_or_equal_to])
end
end

def find_numericality_validator
find_validator(ActiveModel::Validations::NumericalityValidator)
end

def evaluate_validator_option(option)
if option.is_a?(Numeric)
option
elsif option.is_a?(Symbol)
object.send(option)
elsif option.respond_to?(:call)
option.call(object)
end
end
end
end
end

0 comments on commit f883b20

Please sign in to comment.