File: numericality.rb

package info (click to toggle)
ruby-aws-sdk 1.67.0-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 6,840 kB
  • sloc: ruby: 28,436; makefile: 7
file content (136 lines) | stat: -rw-r--r-- 3,935 bytes parent folder | download | duplicates (4)
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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
# Copyright 2011-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"). You
# may not use this file except in compliance with the License. A copy of
# the License is located at
#
#     http://aws.amazon.com/apache2.0/
#
# or in the "license" file accompanying this file. This file is
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
# ANY KIND, either express or implied. See the License for the specific
# language governing permissions and limitations under the License.

module AWS
  module Record

    # @api private
    class NumericalityValidator < Validator

      ACCEPTED_OPTIONS = [
        :greater_than, :greater_than_or_equal_to,
        :less_than, :less_than_or_equal_to,
        :equal_to, :only_integer, :odd, :even,
        :message, :allow_nil, :allow_blank, :on, :if, :unless,
      ]

      COMPARISONS = {
        :equal_to => :==,
        :greater_than => :>,
        :greater_than_or_equal_to => :>=,
        :less_than => :<,
        :less_than_or_equal_to => :<=,
        :even => lambda{|value| value.to_i % 2 == 0 },
        :odd => lambda{|value| value.to_i % 2 == 1 },
      }

      def setup record_class

        ensure_exclusive(:odd, :even)

        ensure_exclusive(:equal_to,
          [:greater_than, :greater_than_or_equal_to,
           :less_than, :less_than_or_equal_to])

        ensure_type([TrueClass, FalseClass], :only_integer)

        ensure_type(TrueClass, :odd, :even)

        ensure_type([Numeric, Symbol, Proc],
          :greater_than, :greater_than_or_equal_to,
          :less_than, :less_than_or_equal_to,
          :equal_to)

      end

      def read_attribute_for_validation(record, attribute_name)
        if record.respond_to?("#{attribute_name}_before_type_cast")
          record.send("#{attribute_name}_before_type_cast")
        else
          record.send(attribute_name)
        end
      end

      def validate_attribute record, attribute_name, raw
        each_value(raw) do |raw_value|

          if options[:only_integer] or options[:odd] or options[:even]
            value = as_integer(raw_value)
            error_type = :not_an_integer
          else
            value = as_number(raw_value)
            error_type = :not_a_number
          end

          unless value
            record.errors.add(attribute_name, message_for(error_type))
            return
          end

          COMPARISONS.each do |option,method|

            next unless options.has_key?(option)

            requirement = case options[option]
            when Symbol then record.send(options[option])
            when Proc then options[option].call(record)
            else options[option]
            end

            valid = case method
            when Symbol then value.send(method, requirement)
            else method.call(value)
            end

            unless valid
              message = message_for(option, requirement)
              record.errors.add(attribute_name, message)
            end

          end
        end
      end

      def message_for error_type, requirement = nil
        return options[:message] if options[:message]
        case error_type
        when :not_a_number   then 'is not a number'
        when :not_an_integer then 'must be an integer'
        when :even           then 'must be an even number'
        when :odd            then 'must be an odd number'
        when :equal_to       then "should equal #{requirement}"
        else
          "must be #{error_type.to_s.gsub(/_/, ' ')} #{requirement}"
        end
      end

      def as_number value
        begin
          Kernel.Float(value)
        rescue ArgumentError, TypeError
          nil
        end
      end

      def as_integer value
        begin
          Kernel.Integer(value)
        rescue ArgumentError, TypeError
          nil
        end
      end

    end

  end
end