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