lib/active_model/validations/numericality.rb in activemodel-7.0.8.6 vs lib/active_model/validations/numericality.rb in activemodel-7.1.0.beta1
- old
+ new
@@ -1,19 +1,21 @@
# frozen_string_literal: true
require "active_model/validations/comparability"
+require "active_model/validations/resolve_value"
require "bigdecimal/util"
module ActiveModel
module Validations
class NumericalityValidator < EachValidator # :nodoc:
include Comparability
+ include ResolveValue
RANGE_CHECKS = { in: :in? }
NUMBER_CHECKS = { odd: :odd?, even: :even? }
- RESERVED_OPTIONS = COMPARE_CHECKS.keys + NUMBER_CHECKS.keys + RANGE_CHECKS.keys + [:only_integer]
+ RESERVED_OPTIONS = COMPARE_CHECKS.keys + NUMBER_CHECKS.keys + RANGE_CHECKS.keys + [:only_integer, :only_numeric]
INTEGER_REGEX = /\A[+-]?\d+\z/
HEXADECIMAL_REGEX = /\A[+-]?0[xX]/
@@ -62,11 +64,11 @@
end
end
private
def option_as_number(record, option_value, precision, scale)
- parse_as_number(option_value(record, option_value), precision, scale)
+ parse_as_number(resolve_value(record, option_value), precision, scale)
end
def parse_as_number(raw_value, precision, scale)
if raw_value.is_a?(Float)
parse_float(raw_value, precision, scale)
@@ -88,10 +90,14 @@
def round(raw_value, scale)
scale ? raw_value.round(scale) : raw_value
end
def is_number?(raw_value, precision, scale)
+ if options[:only_numeric] && !raw_value.is_a?(Numeric)
+ return false
+ end
+
!parse_as_number(raw_value, precision, scale).nil?
rescue ArgumentError, TypeError
false
end
@@ -108,18 +114,11 @@
filtered[:value] = value
filtered
end
def allow_only_integer?(record)
- case options[:only_integer]
- when Symbol
- record.send(options[:only_integer])
- when Proc
- options[:only_integer].call(record)
- else
- options[:only_integer]
- end
+ resolve_value(record, options[:only_integer])
end
def prepare_value_for_validation(value, record, attr_name)
return value if record_attribute_changed_in_place?(record, attr_name)
@@ -147,40 +146,53 @@
end
end
module HelperMethods
# Validates whether the value of the specified attribute is numeric by
- # trying to convert it to a float with Kernel.Float (if <tt>only_integer</tt>
- # is +false+) or applying it to the regular expression <tt>/\A[\+\-]?\d+\z/</tt>
- # (if <tt>only_integer</tt> is set to +true+). Precision of Kernel.Float values
- # are guaranteed up to 15 digits.
+ # trying to convert it to a float with +Kernel.Float+ (if
+ # <tt>only_integer</tt> is +false+) or applying it to the regular
+ # expression <tt>/\A[\+\-]?\d+\z/</tt> (if <tt>only_integer</tt> is set to
+ # +true+). Precision of +Kernel.Float+ values are guaranteed up to 15
+ # digits.
#
# class Person < ActiveRecord::Base
# validates_numericality_of :value, on: :create
# end
#
# Configuration options:
# * <tt>:message</tt> - A custom error message (default is: "is not a number").
# * <tt>:only_integer</tt> - Specifies whether the value has to be an
# integer (default is +false+).
+ # * <tt>:only_numeric</tt> - Specifies whether the value has to be an
+ # instance of Numeric (default is +false+). The default behavior is to
+ # attempt parsing the value if it is a String.
# * <tt>:allow_nil</tt> - Skip validation if attribute is +nil+ (default is
# +false+). Notice that for Integer and Float columns empty strings are
# converted to +nil+.
# * <tt>:greater_than</tt> - Specifies the value must be greater than the
- # supplied value.
+ # supplied value. The default error message for this option is _"must be
+ # greater than %{count}"_.
# * <tt>:greater_than_or_equal_to</tt> - Specifies the value must be
- # greater than or equal the supplied value.
+ # greater than or equal the supplied value. The default error message
+ # for this option is _"must be greater than or equal to %{count}"_.
# * <tt>:equal_to</tt> - Specifies the value must be equal to the supplied
- # value.
+ # value. The default error message for this option is _"must be equal to
+ # %{count}"_.
# * <tt>:less_than</tt> - Specifies the value must be less than the
- # supplied value.
+ # supplied value. The default error message for this option is _"must be
+ # less than %{count}"_.
# * <tt>:less_than_or_equal_to</tt> - Specifies the value must be less
- # than or equal the supplied value.
+ # than or equal the supplied value. The default error message for this
+ # option is _"must be less than or equal to %{count}"_.
# * <tt>:other_than</tt> - Specifies the value must be other than the
- # supplied value.
- # * <tt>:odd</tt> - Specifies the value must be an odd number.
- # * <tt>:even</tt> - Specifies the value must be an even number.
- # * <tt>:in</tt> - Check that the value is within a range.
+ # supplied value. The default error message for this option is _"must be
+ # other than %{count}"_.
+ # * <tt>:odd</tt> - Specifies the value must be an odd number. The default
+ # error message for this option is _"must be odd"_.
+ # * <tt>:even</tt> - Specifies the value must be an even number. The
+ # default error message for this option is _"must be even"_.
+ # * <tt>:in</tt> - Check that the value is within a range. The default
+ # error message for this option is _"must be in %{count}"_.
#
# There is also a list of default options supported by every validator:
# +:if+, +:unless+, +:on+, +:allow_nil+, +:allow_blank+, and +:strict+ .
# See ActiveModel::Validations::ClassMethods#validates for more information.
#