class DataMapper::Validations::NumericalityValidator

@author Guy van den Berg @since 0.9

Public Instance Methods

call(target) click to toggle source
# File lib/dm-validations/validators/numeric_validator.rb, line 7
def call(target)
  value = target.validation_property_value(field_name)
  return true if optional?(value)

  errors = []

  validate_with(integer_only? ? :integer : :numeric, value, errors)

  add_errors(target, errors)

  # if the number is invalid, skip further tests
  return false if errors.any?

  [ :gt, :lt, :gte, :lte, :eq, :ne ].each do |validation_type|
    validate_with(validation_type, value, errors)
  end

  add_errors(target, errors)

  errors.empty?
end

Private Instance Methods

add_errors(target, errors) click to toggle source
# File lib/dm-validations/validators/numeric_validator.rb, line 44
def add_errors(target, errors)
  return if errors.empty?

  if options.key?(:message)
    add_error(target, options[:message], field_name)
  else
    errors.each do |error_message|
      add_error(target, error_message, field_name)
    end
  end
end
integer_only?() click to toggle source
# File lib/dm-validations/validators/numeric_validator.rb, line 31
def integer_only?
  options[:only_integer] || options.fetch(:integer_only, false)
end
validate_eq(value, errors) click to toggle source
# File lib/dm-validations/validators/numeric_validator.rb, line 121
def validate_eq(value, errors)
  eq = options[:eq] || options[:equal] || options[:equals] || options[:exactly] || options[:equal_to]
  validate_with_comparison(value, :==, eq, :equal_to, errors)
end
validate_gt(value, errors) click to toggle source
# File lib/dm-validations/validators/numeric_validator.rb, line 105
def validate_gt(value, errors)
  validate_with_comparison(value, :>, options[:gt] || options[:greater_than], :greater_than, errors)
end
validate_gte(value, errors) click to toggle source
# File lib/dm-validations/validators/numeric_validator.rb, line 113
def validate_gte(value, errors)
  validate_with_comparison(value, :>=, options[:gte] || options[:greater_than_or_equal_to], :greater_than_or_equal_to, errors)
end
validate_integer(value, errors) click to toggle source
# File lib/dm-validations/validators/numeric_validator.rb, line 80
def validate_integer(value, errors)
  validate_with_comparison(value_as_string(value), :=~, /\A[+-]?\d+\z/, :not_an_integer, errors)
end
validate_lt(value, errors) click to toggle source
# File lib/dm-validations/validators/numeric_validator.rb, line 109
def validate_lt(value, errors)
  validate_with_comparison(value, :<, options[:lt] || options[:less_than], :less_than, errors)
end
validate_lte(value, errors) click to toggle source
# File lib/dm-validations/validators/numeric_validator.rb, line 117
def validate_lte(value, errors)
  validate_with_comparison(value, :<=, options[:lte] || options[:less_than_or_equal_to], :less_than_or_equal_to, errors)
end
validate_ne(value, errors) click to toggle source
# File lib/dm-validations/validators/numeric_validator.rb, line 126
def validate_ne(value, errors)
  validate_with_comparison(value, :==, options[:ne] || options[:not_equal_to], :not_equal_to, errors, true)
end
validate_numeric(value, errors) click to toggle source
# File lib/dm-validations/validators/numeric_validator.rb, line 84
def validate_numeric(value, errors)
  precision = options[:precision]
  scale     = options[:scale]

  regexp = if precision && scale
    if precision > scale && scale == 0
      /\A[+-]?(?:\d{1,#{precision}}(?:\.0)?)\z/
    elsif precision > scale
      /\A[+-]?(?:\d{1,#{precision - scale}}|\d{0,#{precision - scale}}\.\d{1,#{scale}})\z/
    elsif precision == scale
      /\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
  else
    /\A[+-]?(?:\d+|\d*\.\d+)\z/
  end

  validate_with_comparison(value_as_string(value), :=~, regexp, :not_a_number, errors)
end
validate_with(validation_type, value, errors) click to toggle source
# File lib/dm-validations/validators/numeric_validator.rb, line 56
def validate_with(validation_type, value, errors)
  send("validate_#{validation_type}", value, errors)
end
validate_with_comparison(value, cmp, expected, error_message_name, errors, negated = false) click to toggle source
# File lib/dm-validations/validators/numeric_validator.rb, line 60
def validate_with_comparison(value, cmp, expected, error_message_name, errors, negated = false)
  return if expected.nil?

  # XXX: workaround for jruby. This is needed because the jruby
  # compiler optimizes a bit too far with magic variables like $~.
  # the value.send line sends $~. Inserting this line makes sure the
  # jruby compiler does not optimise here.
  # see http://jira.codehaus.org/browse/JRUBY-3765
  $~ = nil if RUBY_PLATFORM[/java/]

  comparison = value.send(cmp, expected)
  return if negated ? !comparison : comparison

  errors << ValidationErrors.default_error_message(
    error_message_name,
    field_name,
    expected
  )
end
value_as_string(value) click to toggle source
# File lib/dm-validations/validators/numeric_validator.rb, line 35
def value_as_string(value)
  case value
    # Avoid Scientific Notation in Float to_s
    when Float      then value.to_d.to_s('F')
    when BigDecimal then value.to_s('F')
    else value.to_s
  end
end