Nested Records are Not Instantiated
Opened this issue · 2 comments
When I define an Avromatic class, and instantiate it, I expect all the nested records to also be instantiated. Instead, only the top-most record is instantiated, and any sub-records are nil.
Here's a simple reproduction:
Avro Schema:
{
"type": "record",
"name": "top_rec",
"namespace": "com.example",
"fields": [
{
"name": "sub",
"type": {
"type": "record",
"name": "sub_rec",
"namespace": "com.example",
"fields": [
{
"name": "i",
"type": "int"
}
]
}
}
]
}
Then we load the schema and create a class:
schema_file = File.read('top_rec.avsc')
schema = Avro::Schema.parse(schema_file)
nestedClass = Avromatic::Model.model(schema: schema)
myClass = nestedClass.new
puts myClass.inspect
Actual Result:
#<TopRec sub: nil>
Expected Result:
#<TopRec sub: #<SubRec i: nil>>
Obviously, it's possible to manually instantiate the entire class hierarchy, but this quickly becomes difficult as the level of nesting increases.
I am having the same issue, did you find a work around?
Sorry. We don't have a fix yet, mainly because we've moved to creating immutable models by default for performance reasons and this defaulting is likely to result in a model tree that's invalid and can't be made valid. I definitely see how it could be useful when dealing with mutable models though. In the meantime, you could workaround it via something like:
module ModelNestedRecordDefaulting
EMPTY_HASH = {}.freeze
def initialize(...)
super
attribute_definitions.each do |attribute_name, attribute_definition|
if attribute_definition.type.is_a?(Avromatic::Model::Types::RecordType) && send(attribute_name).nil?
send(attribute_definition.setter_name, EMPTY_HASH)
end
end
end
end
# Include it in specific models
Avromatic::Model.model(schema: schema).include(ModelNestedRecordDefaulting)
# Alternatively patch it in globally for all models
module BuilderInclusionsPatch
def inclusions
super + [ModelNestedRecordDefaulting]
end
end
Avromatic::Model::Builder.prepend(BuilderInclusionsPatch)