Class: Schemacop::V3::NumericNode Abstract

Inherits:
Node
  • Object
show all
Defined in:
lib/schemacop/v3/numeric_node.rb

Overview

This class is abstract.

Direct Known Subclasses

IntegerNode, NumberNode

Constant Summary collapse

ATTRIBUTES =
i[
  minimum
  maximum
  multiple_of
  exclusive_minimum
  exclusive_maximum
  max_precision
].freeze

Instance Attribute Summary

Attributes inherited from Node

#as, #default, #description, #name, #options, #parent, #require_key, #title

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Node

#allowed_types, #as_json, #cast, #cast_str_wrapper?, #children, create, #create, dsl_methods, #dsl_node, #dsl_scm, #init, #initialize, #require_key?, #required?, resolve_class, #schemas, supports_children, supports_children_options, #used_external_schemas, #validate

Constructor Details

This class inherits a constructor from Schemacop::V3::Node

Class Method Details

.allowed_optionsObject



14
15
16
# File 'lib/schemacop/v3/numeric_node.rb', line 14

def self.allowed_options
  super + ATTRIBUTES + i[cast_str]
end

Instance Method Details

#_validate(data, result:) ⇒ Object



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
# File 'lib/schemacop/v3/numeric_node.rb', line 36

def _validate(data, result:)
  super_data = super
  return if super_data.nil?

  # Validate minimum #
  if options[:minimum] && super_data < options[:minimum]
    result.error "Value must have a minimum of #{options[:minimum]}."
  end

  if options[:exclusive_minimum] && super_data <= options[:exclusive_minimum]
    result.error "Value must have an exclusive minimum of #{options[:exclusive_minimum]}."
  end

  # Validate maximum #
  if options[:maximum] && super_data > options[:maximum]
    result.error "Value must have a maximum of #{options[:maximum]}."
  end

  if options[:exclusive_maximum] && super_data >= options[:exclusive_maximum]
    result.error "Value must have an exclusive maximum of #{options[:exclusive_maximum]}."
  end

  # Validate multiple of #
  if options[:multiple_of] && !compare_float((super_data % options[:multiple_of]), 0.0)
    result.error "Value must be a multiple of #{options[:multiple_of]}."
  end

  # Validate max precision #
  if options[:max_precision] && (super_data.is_a?(Float) || super_data.is_a?(BigDecimal))
    # Convert to string and check decimal places
    str = super_data.to_s
    # For BigDecimal, remove the trailing '0' from the scientific notation if present
    str = str.sub(/\.0e[+-]?\d+\z/, '.0') if super_data.is_a?(BigDecimal)

    if (match = str.match(/\.(\d+)$/))
      # Remove trailing zeros for more accurate precision check
      decimal_part = match[1].sub(/0+\z/, '')
      decimal_places = decimal_part.empty? ? 0 : decimal_part.length
      if decimal_places > options[:max_precision]
        result.error "Value must have a maximum precision of #{options[:max_precision]} digits after the decimal point."
      end
    end
  end
end

#process_json(attrs, json) ⇒ Object



18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/schemacop/v3/numeric_node.rb', line 18

def process_json(attrs, json)
  if context.swagger_json?
    if options[:exclusive_minimum]
      json[:minimum] = options[:exclusive_minimum]
      json[:exclusiveMinimum] = true
    end

    if options[:exclusive_maximum]
      json[:maximum] = options[:exclusive_maximum]
      json[:exclusiveMaximum] = true
    end

    attrs -= i[exclusive_minimum exclusive_maximum]
  end

  super
end

#validate_selfObject



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
# File 'lib/schemacop/v3/numeric_node.rb', line 81

def validate_self
  # Check that the options have the correct type
  ATTRIBUTES.each do |attribute|
    next if options[attribute].nil?

    # Special handling for max_precision - must be an integer
    if attribute == :max_precision
      unless options[attribute].is_a?(Integer) && options[attribute] >= 0
        fail 'Option "max_precision" must be a non-negative integer.'
      end

      next
    end

    next unless allowed_types.keys.none? { |c| options[attribute].send(type_assertion_method, c) }

    collection = allowed_types.values.map { |t| "\"#{t}\"" }.uniq.sort.join(' or ')
    fail "Option \"#{attribute}\" must be a #{collection}"
  end

  if options[:minimum] && options[:maximum] && options[:minimum] > options[:maximum]
    fail 'Option "minimum" can\'t be greater than "maximum".'
  end

  if options[:exclusive_minimum] && options[:exclusive_maximum] \
     && options[:exclusive_minimum] > options[:exclusive_maximum]
    fail 'Option "exclusive_minimum" can\'t be greater than "exclusive_maximum".'
  end

  if options[:multiple_of]&.zero?
    fail 'Option "multiple_of" can\'t be 0.'
  end
end