Module: FlyIO::SchemaValidator

Defined in:
lib/fly_io/schema_validator.rb

Class Method Summary collapse

Class Method Details

.validate!(schema, value, location: "value") ⇒ Object



7
8
9
10
11
12
13
14
15
16
17
# File 'lib/fly_io/schema_validator.rb', line 7

def validate!(schema, value, location: "value")
  return if schema.nil? || !schema.is_a?(Hash)

  schema = SchemaRegistry.flatten_all_of(SchemaRegistry.resolve(schema))
  raw = value.is_a?(Model) ? value.to_h : value
  validate_type!(schema["type"], raw, location)
  validate_enum!(schema["enum"], raw, location)
  validate_object!(schema, raw, location) if raw.is_a?(Hash)
  validate_array!(schema, raw, location) if raw.is_a?(Array)
  true
end

.validate_array!(schema, value, location) ⇒ Object



52
53
54
# File 'lib/fly_io/schema_validator.rb', line 52

def validate_array!(schema, value, location)
  value.each_with_index { |item, index| validate!(schema["items"], item, location: "#{location}[#{index}]") }
end

.validate_enum!(enum, value, location) ⇒ Object



34
35
36
37
38
# File 'lib/fly_io/schema_validator.rb', line 34

def validate_enum!(enum, value, location)
  return unless enum && !value.nil? && !enum.include?(value)

  raise FlyIO::ArgumentError, "#{location} must be one of: #{enum.join(', ')}"
end

.validate_object!(schema, value, location) ⇒ Object



40
41
42
43
44
45
46
47
48
49
50
# File 'lib/fly_io/schema_validator.rb', line 40

def validate_object!(schema, value, location)
  normalized = value.transform_keys(&:to_s)
  Array(schema["required"]).each do |name|
    unless normalized.key?(name) && !normalized[name].nil?
      raise FlyIO::ArgumentError, "#{location}.#{name} is required"
    end
  end
  schema.fetch("properties", {}).each do |name, property_schema|
    validate!(property_schema, normalized[name], location: "#{location}.#{name}") if normalized.key?(name)
  end
end

.validate_type!(type, value, location) ⇒ Object



19
20
21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/fly_io/schema_validator.rb', line 19

def validate_type!(type, value, location)
  return if type.nil? || value.nil?

  valid = case type
          when "object" then value.is_a?(Hash)
          when "array" then value.is_a?(Array)
          when "string" then value.is_a?(String)
          when "integer" then value.is_a?(Integer)
          when "number" then value.is_a?(Numeric)
          when "boolean" then [true, false].include?(value)
          else true
          end
  raise FlyIO::ArgumentError, "#{location} must be #{type}" unless valid
end