From f883b20b94d9bd74d3a38ed189619b809a672385 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Sun, 4 Dec 2011 16:31:13 +0100 Subject: [PATCH] Make min_max also a component. --- .../config/initializers/simple_form.rb | 14 ++--- lib/simple_form.rb | 1 + lib/simple_form/components.rb | 1 + lib/simple_form/components/min_max.rb | 51 +++++++++++++++++++ lib/simple_form/inputs/base.rb | 5 +- lib/simple_form/inputs/numeric_input.rb | 47 +---------------- 6 files changed, 65 insertions(+), 54 deletions(-) create mode 100644 lib/simple_form/components/min_max.rb diff --git a/lib/generators/simple_form/templates/config/initializers/simple_form.rb b/lib/generators/simple_form/templates/config/initializers/simple_form.rb index c88ec7f9..ee4bbd83 100644 --- a/lib/generators/simple_form/templates/config/initializers/simple_form.rb +++ b/lib/generators/simple_form/templates/config/initializers/simple_form.rb @@ -10,14 +10,16 @@ SimpleForm.setup do |config| 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 diff --git a/lib/simple_form.rb b/lib/simple_form.rb index a6a5c59d..21abfd2b 100644 --- a/lib/simple_form.rb +++ b/lib/simple_form.rb @@ -144,6 +144,7 @@ module SimpleForm 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 diff --git a/lib/simple_form/components.rb b/lib/simple_form/components.rb index a53b284b..9932ae24 100644 --- a/lib/simple_form/components.rb +++ b/lib/simple_form/components.rb @@ -11,6 +11,7 @@ module SimpleForm 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' diff --git a/lib/simple_form/components/min_max.rb b/lib/simple_form/components/min_max.rb new file mode 100644 index 00000000..72b1af47 --- /dev/null +++ b/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 \ No newline at end of file diff --git a/lib/simple_form/inputs/base.rb b/lib/simple_form/inputs/base.rb index 53e40071..f7e27a8c 100644 --- a/lib/simple_form/inputs/base.rb +++ b/lib/simple_form/inputs/base.rb @@ -13,6 +13,7 @@ module SimpleForm 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 @@ -44,7 +45,7 @@ module SimpleForm 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 @@ -54,7 +55,7 @@ module SimpleForm @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. diff --git a/lib/simple_form/inputs/numeric_input.rb b/lib/simple_form/inputs/numeric_input.rb index e029644f..10723532 100644 --- a/lib/simple_form/inputs/numeric_input.rb +++ b/lib/simple_form/inputs/numeric_input.rb @@ -1,7 +1,7 @@ module SimpleForm module Inputs class NumericInput < Base - enable :placeholder + enable :placeholder, :min_max def input add_size! @@ -9,7 +9,6 @@ module SimpleForm 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 @@ -20,50 +19,6 @@ module SimpleForm 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