lib/dry/struct/class_interface.rb in dry-struct-0.3.0 vs lib/dry/struct/class_interface.rb in dry-struct-0.3.1

- old
+ new

@@ -1,32 +1,25 @@ require 'dry/core/class_attributes' require 'dry/equalizer' require 'dry/struct/errors' +require 'dry/struct/constructor' module Dry class Struct # Class-level interface of {Struct} and {Value} module ClassInterface include Core::ClassAttributes include Dry::Types::Builder - # @param [Module] base - def self.extended(base) - base.instance_variable_set(:@schema, EMPTY_HASH) - end - # @param [Class] klass def inherited(klass) super - klass.instance_variable_set(:@schema, EMPTY_HASH) klass.equalizer Equalizer.new(*schema.keys) klass.send(:include, klass.equalizer) - - klass.attributes(EMPTY_HASH) unless equal?(Struct) end # Adds an attribute for this {Struct} with given `name` and `type` # and modifies {.schema} accordingly. # @@ -67,13 +60,11 @@ # #=> {title: #<Dry::Types::Definition primitive=String options={}>, # # author: #<Dry::Types::Definition primitive=String options={}>} def attributes(new_schema) check_schema_duplication(new_schema) - prev_schema = schema - - @schema = prev_schema.merge(new_schema) + schema schema.merge(new_schema) input Types['coercible.hash'].public_send(constructor_type, schema) attr_reader(*new_schema.keys) equalizer.instance_variable_get('@keys').concat(new_schema.keys) @@ -88,16 +79,10 @@ raise RepeatedAttributeError, shared_keys.first if shared_keys.any? end private :check_schema_duplication - # @return [Hash{Symbol => Dry::Types::Definition, Dry::Struct}] - def schema - super_schema = superclass.respond_to?(:schema) ? superclass.schema : EMPTY_HASH - super_schema.merge(@schema) - end - # @param [Hash{Symbol => Object},Dry::Struct] attributes # @raise [Struct::Error] if the given attributes don't conform {#schema} # with given {#constructor_type} def new(attributes = default_attributes) if attributes.instance_of?(self) @@ -108,20 +93,28 @@ rescue Types::SchemaError, Types::MissingKeyError, Types::UnknownKeysError => error raise Struct::Error, "[#{self}.new] #{error}" end # Calls type constructor. The behavior is identical to `.new` but returns - # returns the input back if it's a subclass of the struct. + # the input back if it's a subclass of the struct. # # @param [Hash{Symbol => Object},Dry::Struct] attributes # @return [Dry::Struct] def call(attributes = default_attributes) return attributes if attributes.is_a?(self) new(attributes) end alias_method :[], :call + # @param [#call,nil] constructor + # @param [Hash] options + # @param [#call,nil] block + # @return [Dry::Struct::Constructor] + def constructor(constructor = nil, **_options, &block) + Struct::Constructor.new(self, fn: constructor || block) + end + # Retrieves default attributes from defined {.schema}. # Used in a {Struct} constructor if no attributes provided to {.new} # # @return [Hash{Symbol => Object}] def default_attributes @@ -191,9 +184,24 @@ end # @return [false] def optional? false + end + + # Checks if this {Struct} has the given attribute + # + # @param [Symbol] key Attribute name + # @return [Boolean] + def attribute?(key) + schema.key?(key) + end + + # Gets the list of attribute names + # + # @return [Array<Symbol>] + def attribute_names + schema.keys end end end end