Class: Deimos::AvroSchemaCoercer

Inherits:
Object
  • Object
show all
Defined in:
lib/deimos/schema_backends/avro_schema_coercer.rb

Overview

Class to coerce values in a payload to match a schema.

Instance Method Summary collapse

Constructor Details

#initialize(schema) ⇒ AvroSchemaCoercer



9
10
11
# File 'lib/deimos/schema_backends/avro_schema_coercer.rb', line 9

def initialize(schema)
  @schema = schema
end

Instance Method Details

#coerce_record(type, val) ⇒ Object

Coerce sub-records in a payload to match the schema.



29
30
31
32
33
34
35
# File 'lib/deimos/schema_backends/avro_schema_coercer.rb', line 29

def coerce_record(type, val)
  record = val.map do |name, value|
    field = type.fields.find { |f| f.name == name }
    coerce_type(field.type, value)
  end
  val.keys.zip(record).to_h
end

#coerce_type(type, val) ⇒ Object

Coerce values in a payload to match the schema.



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
# File 'lib/deimos/schema_backends/avro_schema_coercer.rb', line 41

def coerce_type(type, val)
  int_classes = [Time, ActiveSupport::TimeWithZone]
  field_type = type.type.to_sym

  case field_type
  when :int, :long
    if %w(timestamp-millis timestamp-micros).include?(type.logical_type)
      val
    elsif val.is_a?(Integer) ||
          _is_integer_string?(val) ||
          int_classes.any? { |klass| val.is_a?(klass) }
      val.to_i
    else
      val # this will fail
    end
  when :float, :double
    if val.is_a?(Numeric) || _is_float_string?(val)
      val.to_f
    else
      val # this will fail
    end
  when :string
    if val.respond_to?(:to_str)
      val.to_s
    elsif _is_to_s_defined?(val)
      val.to_s
    else
      val # this will fail
    end
  when :boolean
    if val.nil? || val == false
      false
    else
      true
    end
  when :union
    coerce_union(type, val)
  when :record
    coerce_record(type, val)
  else
    val
  end
end

#coerce_union(type, val) ⇒ Object

Coerce sub-records in a payload to match the schema.



17
18
19
20
21
22
23
# File 'lib/deimos/schema_backends/avro_schema_coercer.rb', line 17

def coerce_union(type, val)
  union_types = type.schemas.map { |s| s.type.to_sym }
  return nil if val.nil? && union_types.include?(:null)

  schema_type = type.schemas.find { |s| s.type.to_sym != :null }
  coerce_type(schema_type, val)
end