class AMA::Entity::Mapper::Type
Type
wrapper
Attributes
@!attribute attributes
@return [Hash{Symbol, AMA::Entity::Mapper::Type::Attribute}]
@!attribute parameters
@return [Hash{Symbol, AMA::Entity::Mapper::Type::Parameter}]
@!attribute type
@return [Class]
@!attribute virtual
@return [TrueClass, FalseClass]
Public Class Methods
@param [Class, Module] klass
# File lib/ama-entity-mapper/type.rb, line 62 def initialize(klass, virtual: false) @type = validate_type!(klass) @parameters = {} @attributes = {} @virtual = virtual end
Public Instance Methods
# File lib/ama-entity-mapper/type.rb, line 179 def ==(other) eql?(other) end
Shortcut for attribute creation.
@param [String, Symbol] name @param [Array<AMA::Entity::Mapper::Type>] types @param [Hash] options
# File lib/ama-entity-mapper/type.rb, line 101 def attribute!(name, *types, **options) name = name.to_sym types = types.map do |type| next type if type.is_a?(Parameter) next parameter!(type) if type.is_a?(Symbol) next self.class.new(type) unless type.is_a?(Type) type end attributes[name] = Attribute.new(self, name, *types, **options) end
# File lib/ama-entity-mapper/type.rb, line 174 def eql?(other) return false unless other.is_a?(self.class) @type == other.type && @attributes == other.attributes end
# File lib/ama-entity-mapper/type.rb, line 170 def hash @type.hash ^ @attributes.hash end
# File lib/ama-entity-mapper/type.rb, line 79 def instance!(object, context) return if instance?(object) message = "Provided object #{object} is not an instance of #{self}" validation_error(message, context: context) end
Tells if provided object is an instance of this type.
This doesn't mean all of it's attributes do match requested types.
@param [Object] object @return [TrueClass, FalseClass]
# File lib/ama-entity-mapper/type.rb, line 75 def instance?(object) object.is_a?(@type) end
Creates new type parameter
@param [Symbol] id @return [Parameter]
# File lib/ama-entity-mapper/type.rb, line 116 def parameter!(id) id = id.to_sym return @parameters[id] if @parameters.key?(id) @parameters[id] = Parameter.new(self, id) end
@param [Hash<AMA::Entity::Mapper::Type, AMA::Entity::Mapper::Type>] parameters @return [AMA::Entity::Mapper::Type]
# File lib/ama-entity-mapper/type.rb, line 146 def resolve(parameters) parameters.reduce(self) do |carrier, tuple| carrier.resolve_parameter(*tuple) end end
Resolves single parameter type. Substitution may be either another parameter or array of types.
@param [Parameter] parameter @param [Parameter, Array<Type>] substitution
# File lib/ama-entity-mapper/type.rb, line 127 def resolve_parameter(parameter, substitution) parameter = validate_parameter!(parameter) substitution = validate_substitution!(substitution) clone.tap do |clone| intermediate = attributes.map do |key, value| [key, value.resolve_parameter(parameter, substitution)] end clone.attributes = Hash[intermediate] intermediate = clone.parameters.map do |key, value| [key, value == parameter ? substitution : value] end clone.parameters = Hash[intermediate] end end
Validates that type is fully resolved, otherwise raises an error @param [AMA::Entity::Mapper::Context] context
# File lib/ama-entity-mapper/type.rb, line 92 def resolved!(context = Context.new) attributes.values.each { |attribute| attribute.resolved!(context) } end
@return [TrueClass, FalseClass]
# File lib/ama-entity-mapper/type.rb, line 86 def resolved? attributes.values.all?(&:resolved?) end
# File lib/ama-entity-mapper/type.rb, line 191 def to_def return @type.to_s if parameters.empty? params = parameters.map do |key, value| value = [value] unless value.is_a?(Enumerable) value = value.map(&:to_def) value = value.size > 1 ? "[#{value.join(', ')}]" : value.first "#{key}:#{value}" end "#{@type}<#{params.join(', ')}>" end
# File lib/ama-entity-mapper/type.rb, line 183 def to_s message = "Type #{@type}" unless @parameters.empty? message += " (parameters: #{@parameters.keys})" end message end
# File lib/ama-entity-mapper/type.rb, line 162 def valid!(object, context) violations = self.violations(object, context) return if violations.empty? message = "#{object} has failed type #{to_def} validation: " \ "#{violations.join(', ')}" validation_error(message, context: context) end
# File lib/ama-entity-mapper/type.rb, line 158 def valid?(object, context) violations(object, context).empty? end
rubocop:enable Metrics/LineLength
# File lib/ama-entity-mapper/type.rb, line 154 def violations(object, context) validator.validate(object, self, context) end
Private Instance Methods
# File lib/ama-entity-mapper/type.rb, line 211 def validate_parameter!(parameter) return parameter if parameter.is_a?(Parameter) message = "Non-parameter type #{parameter} " \ 'supplied for resolution' compliance_error(message) end
# File lib/ama-entity-mapper/type.rb, line 218 def validate_substitution!(substitution) return substitution if substitution.is_a?(Parameter) substitution = [substitution] if substitution.is_a?(self.class) if substitution.is_a?(Enumerable) return validate_substitutions!(substitution) end message = 'Provided substitution is neither another Parameter ' \ 'or Array of Types: ' \ "#{substitution} (#{substitution.class})" compliance_error(message) end
# File lib/ama-entity-mapper/type.rb, line 230 def validate_substitutions!(substitutions) if substitutions.empty? compliance_error('Empty list of substitutions passed') end invalid = substitutions.reject do |substitution| substitution.is_a?(Type) end return substitutions if invalid.empty? compliance_error("Invalid substitutions supplied: #{invalid}") end
# File lib/ama-entity-mapper/type.rb, line 204 def validate_type!(type) return type if type.is_a?(Class) || type.is_a?(Module) message = 'Expected Type to be instantiated with ' \ "Class/Module instance, got #{type}" compliance_error(message) end