module JsonbAccessor::ClassBuilder

def generate_class(namespace, new_class_name, attribute_definitions)

def generate_class(namespace, new_class_name, attribute_definitions)
  grouped_attributes = group_attributes(attribute_definitions)
  klass = Class.new(NestedBase)
  namespace.const_set(new_class_name.to_s.camelize, klass)
  nested_classes = generate_nested_classes(klass, grouped_attributes[:nested])
  klass.class_eval do
    singleton_class.send(:define_method, :nested_classes) { nested_classes }
    singleton_class.send(:define_method, :attribute_on_parent_name) { new_class_name }
    define_method(:attributes_and_data_types) do
      @attributes_and_data_types ||= grouped_attributes[:typed].each_with_object({}) do |(name, type), attrs_and_data_types|
        attrs_and_data_types[name] = TypeHelper.fetch(type)
      end
    end
    grouped_attributes[:typed].keys.each do |attribute_name|
      define_method(attribute_name) { attributes[attribute_name] }
      define_method("#{attribute_name}=") do |value|
        cast_value = attributes_and_data_types[attribute_name].type_cast_from_user(value)
        attributes[attribute_name] = cast_value
        update_parent
      end
    end
    grouped_attributes[:nested].keys.each do |attribute_name|
      attr_reader attribute_name
      define_method("#{attribute_name}=") do |value|
        instance_class = nested_classes[attribute_name]
        case value
        when instance_class
          instance = instance_class.new(value.attributes)
        when Hash
          instance = instance_class.new(value)
        when nil
          instance = instance_class.new
        else
          raise UnknownValue, "unable to set value '#{value}' is not a hash, `nil`, or an instance of #{instance_class} in #{__method__}"
        end
        instance.parent = self
        instance_variable_set("@#{attribute_name}", instance)
        attributes[attribute_name] = instance.attributes
        update_parent
      end
    end
  end
  klass
end