Module: Trane::Types

Defined in:
lib/trane/types.rb

Constant Summary collapse

PRIMITIVES =
Set[
  :string, :integer, :float, :boolean,
  :date, :datetime, :object, :array
].freeze
ENUMERABLE_TYPES =

Types that support enum: (scalar primitives only)

Set[
  :string, :integer, :float, :boolean, :date, :datetime
].freeze
HTTP_STATUS_RANGE =
(100..599).freeze

Class Method Summary collapse

Class Method Details

.representation_reference?(type) ⇒ Boolean

Returns:

  • (Boolean)


20
21
22
# File 'lib/trane/types.rb', line 20

def self.representation_reference?(type)
  !type.nil? && !PRIMITIVES.include?(type)
end

.validate_enum!(name:, type:, enum:) ⇒ Object

Validates the structure and content of an enum: declaration. Raises ArgumentError if invalid.



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/trane/types.rb', line 42

def self.validate_enum!(name:, type:, enum:)
  return if enum.nil?

  unless enum.is_a?(Array)
    raise ArgumentError, "field/param :#{name} enum: must be an Array (got #{enum.class})"
  end

  if enum.empty?
    raise ArgumentError, "field/param :#{name} enum: must be a non-empty Array"
  end

  unless ENUMERABLE_TYPES.include?(type)
    raise ArgumentError,
          "field/param :#{name} enum: is only supported for scalar primitive types " \
          "(#{ENUMERABLE_TYPES.to_a.map { |t| ":#{t}" }.join(', ')}). Got :#{type}."
  end

  enum.each do |value|
    unless value_matches_type?(value, type)
      raise ArgumentError,
            "field/param :#{name} enum value #{value.inspect} (#{value.class}) is not coherent with type :#{type}"
    end
  end
end

.value_matches_type?(value, type) ⇒ Boolean

Strict type-match: each value must be EXACTLY of the declared type's class. No coercion (Integer not accepted for :float, DateTime not accepted for :date, etc).

Returns:

  • (Boolean)


26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/trane/types.rb', line 26

def self.value_matches_type?(value, type)
  case type
  when :string   then value.is_a?(String)
  when :integer  then value.is_a?(Integer)
  when :float    then value.is_a?(Float)
  when :boolean  then value.is_a?(TrueClass) || value.is_a?(FalseClass)
  when :date     then value.is_a?(Date) && !value.is_a?(DateTime)
  # !! keeps the return strictly boolean: `defined?` yields nil (not
  # false) when TimeWithZone isn't loaded, and nil would leak out.
  when :datetime then value.is_a?(DateTime) || value.is_a?(Time) ||
                      (!!defined?(ActiveSupport::TimeWithZone) && value.is_a?(ActiveSupport::TimeWithZone))
  else false
  end
end