sam / dm-more

Extras for DataMapper, including bridges to DataObjects::Migrations and Merb::DataMapper

This URL has Read+Write access

dm-more / dm-validations / lib / dm-validations / numeric_validator.rb
100644 64 lines (51 sloc) 2.005 kb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
module DataMapper
  module Validate
 
    ##
    #
    # @author Guy van den Berg
    # @since 0.9
    class NumericValidator < GenericValidator
 
      def initialize(field_name, options={})
        super
        @field_name, @options = field_name, options
        @options[:integer_only] = false unless @options.has_key?(:integer_only)
      end
 
      def call(target)
        value = target.attribute_get(field_name)
        return true if @options[:allow_nil] && value.nil?
 
        value = value.kind_of?(BigDecimal) ? value.to_s('F') : value.to_s
 
        error_message = @options[:message]
        scale = @options[:scale]
        precision = @options[:precision]
 
        if @options[:integer_only]
          return true if value =~ /\A[+-]?\d+\z/
          error_message ||= '%s must be an integer'.t(DataMapper::Inflection.humanize(@field_name))
        else
          if scale && precision
            if scale == precision
              return true if value =~ /\A(?:0\.\d{1,#{precision}})\z/
            elsif precision == 0
              return true if value =~ /\A(?:\d{1,#{scale}}(?:\.0)?)\z/
            else
              return true if value =~ /\A(?:\d{1,#{scale - precision}}|\d{0,#{scale - precision}}\.\d{1,#{precision}})\z/
            end
          else
            return true if value =~ /\A(?:\d+|\d*\.\d+)\z/
          end
          error_message ||= '%s must be a number'.t(DataMapper::Inflection.humanize(@field_name))
        end
 
        add_error(target, error_message, @field_name)
 
        # TODO: check the gt, gte, lt, lte, and eq options
 
        return false
      end
    end # class NumericValidator
 
    module ValidatesIsNumber
 
      # Validate whether a field is numeric
      #
      def validates_is_number(*fields)
        opts = opts_from_validator_args(fields)
        add_validator_to_context(opts, fields, DataMapper::Validate::NumericValidator)
      end
 
    end # module ValidatesIsNumber
  end # module Validate
end # module DataMapper