lib/avromatic/model/attributes.rb in avromatic-2.0.0 vs lib/avromatic/model/attributes.rb in avromatic-2.0.1

- old
+ new

@@ -19,18 +19,19 @@ super("Optional field not allowed: #{field}") end end class AttributeDefinition - attr_reader :name, :type, :field, :default, :owner + attr_reader :name, :setter_name, :type, :field, :default, :owner delegate :serialize, to: :type def initialize(owner:, field:, type:) @owner = owner @field = field @type = type @name = field.name.to_sym + @setter_name = "#{field.name}=".to_sym @default = if field.default == :no_default nil elsif field.default.duplicable? field.default.dup.deep_freeze else @@ -75,17 +76,17 @@ valid_keys = [] attribute_definitions.each do |attribute_name, attribute_definition| if data.include?(attribute_name) valid_keys << attribute_name value = data.fetch(attribute_name) - _attributes[attribute_name] = attribute_definition.coerce(value) + send(attribute_definition.setter_name, value) elsif data.include?(attribute_name.to_s) valid_keys << attribute_name value = data[attribute_name.to_s] - _attributes[attribute_name] = attribute_definition.coerce(value) + send(attribute_definition.setter_name, value) elsif !attributes.include?(attribute_name) - _attributes[attribute_name] = attribute_definition.default + send(attribute_definition.setter_name, attribute_definition.default) end end unless Avromatic.allow_unknown_attributes || valid_keys.size == data.size unknown_attributes = (data.keys.map(&:to_s) - valid_keys.map(&:to_s)).sort @@ -109,25 +110,25 @@ def _attributes @attributes ||= {} end module ClassMethods - def add_avro_fields + def add_avro_fields(generated_methods_module) # models are registered in Avromatic.nested_models at this point to # ensure that they are available as fields for recursive models. register! if key_avro_schema check_for_field_conflicts! begin - define_avro_attributes(key_avro_schema, + define_avro_attributes(key_avro_schema, generated_methods_module, allow_optional: config.allow_optional_key_fields) rescue OptionalFieldError => ex raise "Optional field '#{ex.field.name}' not allowed in key schema." end end - define_avro_attributes(avro_schema) + define_avro_attributes(avro_schema, generated_methods_module) end private def check_for_field_conflicts! @@ -149,11 +150,11 @@ def schema_fields_differ?(name) key_avro_fields_by_name[name].to_avro != value_avro_fields_by_name[name].to_avro end - def define_avro_attributes(schema, allow_optional: true) + def define_avro_attributes(schema, generated_methods_module, allow_optional: true) if schema.type_sym != :record raise "Unsupported schema type '#{schema.type_sym}', only 'record' schemas are supported." end schema.fields.each do |field| @@ -161,35 +162,27 @@ symbolized_field_name = field.name.to_sym attribute_definition = AttributeDefinition.new( owner: self, field: field, - type: create_type(field) + type: Avromatic::Model::Types::TypeFactory.create(schema: field.type, nested_models: nested_models) ) attribute_definitions[symbolized_field_name] = attribute_definition - define_method(field.name) { _attributes[symbolized_field_name] } - define_method("#{field.name}?") { !!_attributes[symbolized_field_name] } if boolean?(field) + # Add all generated methods to a module so they can be overridden + generated_methods_module.send(:define_method, field.name) { _attributes[symbolized_field_name] } + generated_methods_module.send(:define_method, "#{field.name}?") { !!_attributes[symbolized_field_name] } if FieldHelper.boolean?(field) - define_method("#{field.name}=") do |value| + generated_methods_module.send(:define_method, "#{field.name}=") do |value| _attributes[symbolized_field_name] = attribute_definitions[symbolized_field_name].coerce(value) end unless config.mutable # rubocop:disable Style/Next - private("#{field.name}=") - define_method(:clone) { self } - define_method(:dup) { self } + generated_methods_module.send(:private, "#{field.name}=") + generated_methods_module.send(:define_method, :clone) { self } + generated_methods_module.send(:define_method, :dup) { self } end end - end - - def boolean?(field) - field.type.type_sym == :boolean || - (FieldHelper.optional?(field) && field.type.schemas.last.type_sym == :boolean) - end - - def create_type(field) - Avromatic::Model::Types::TypeFactory.create(schema: field.type, nested_models: nested_models) end end end end