def call(target)
value = target.send(field_name)
return true if @options[:allow_nil] && value.nil?
value = (defined?(BigDecimal) && value.kind_of?(BigDecimal)) ? value.to_s('F') : value.to_s
error_message = @options[:message]
precision = @options[:precision]
scale = @options[:scale]
if @options[:integer_only]
return true if value =~ /\A[+-]?\d+\z/
error_message ||= ValidationErrors.default_error_message(:not_an_integer, field_name)
else
if precision && scale
if precision > scale && scale > 0
return true if value =~ /\A[+-]?(?:\d{1,#{precision - scale}}|\d{0,#{precision - scale}}\.\d{1,#{scale}})\z/
elsif precision > scale && scale == 0
return true if value =~ /\A[+-]?(?:\d{1,#{precision}}(?:\.0)?)\z/
elsif precision == scale
return true if value =~ /\A[+-]?(?:0(?:\.\d{1,#{scale}})?)\z/
else
raise ArgumentError, "Invalid precision #{precision.inspect} and scale #{scale.inspect} for #{field_name} (value: #{value.inspect} #{value.class})"
end
elsif precision && scale.nil?
return true if value.gsub(/[^\d]/, '').length <= precision
return true if value =~ /\A[+-]?(?:\d{1,#{precision}}(?:\.0)?)\z/
else
return true if value =~ /\A[+-]?(?:\d+|\d*\.\d+)\z/
end
error_message ||= ValidationErrors.default_error_message(:not_a_number, field_name)
end
add_error(target, error_message, field_name)
return false
end