lib/avromatic/model/attributes.rb in avromatic-0.3.0 vs lib/avromatic/model/attributes.rb in avromatic-0.4.0
- old
+ new
@@ -7,10 +7,19 @@
# This module supports defining Virtus attributes for a model based on the
# fields of Avro schemas.
module Attributes
extend ActiveSupport::Concern
+ def self.first_union_schema(field_type)
+ # TODO: This is a hack until I find a better solution for unions with
+ # Virtus. This only handles a union for an optional field with :null
+ # and one other type.
+ schemas = field_type.schemas.reject { |schema| schema.type_sym == :null }
+ raise "Only the union of null with one other type is supported #{field_type}" if schemas.size > 1
+ schemas.first
+ end
+
module ClassMethods
def add_avro_fields
if key_avro_schema
check_for_field_conflicts!
define_avro_attributes(key_avro_schema)
@@ -46,10 +55,11 @@
attribute(field.name,
field_class,
avro_field_options(field))
add_validation(field)
+ add_serializer(field)
end
end
def add_validation(field)
case field.type.type_sym
@@ -79,10 +89,13 @@
def required?(field)
!optional?(field)
end
def avro_field_class(field_type)
+ custom_type = Avromatic.type_registry.fetch(field_type)
+ return custom_type.value_class if custom_type.value_class
+
case field_type.type_sym
when :string, :bytes, :fixed
String
when :boolean
Axiom::Types::Boolean
@@ -110,26 +123,31 @@
raise "Unsupported type #{field_type}"
end
end
def union_field_class(field_type)
- # TODO: This is a hack until I find a better solution for unions with
- # Virtus. This only handles a union for a optional field with :null
- # and one other type.
- schemas = field_type.schemas.reject { |schema| schema.type_sym == :null }
- raise "Only the union of null with one other type is supported #{field_type}" if schemas.size > 1
- avro_field_class(schemas.first)
+ avro_field_class(Avromatic::Model::Attributes.first_union_schema(field_type))
end
def avro_field_options(field)
+ options = {}
+
+ custom_type = Avromatic.type_registry.fetch(field)
+ coercer = custom_type.deserializer
+ options[:coercer] = coercer if coercer
+
if field.default
- {
- default: default_for(field.default),
- lazy: true
- }
- else
- { }
+ options.merge!(default: default_for(field.default), lazy: true)
end
+
+ options
+ end
+
+ def add_serializer(field)
+ custom_type = Avromatic.type_registry.fetch(field)
+ serializer = custom_type.serializer
+
+ avro_serializer[field.name.to_sym] = serializer if serializer
end
def default_for(value)
value.duplicable? ? value.dup.deep_freeze : value
end