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