Class: AMA::Entity::Mapper::Type

Inherits:
Object
  • Object
show all
Includes:
Mixin::Errors, Mixin::HandlerSupport, Mixin::Reflection
Defined in:
lib/ama-entity-mapper/type.rb,
lib/ama-entity-mapper/type/any.rb,
lib/ama-entity-mapper/type/analyzer.rb,
lib/ama-entity-mapper/type/registry.rb,
lib/ama-entity-mapper/type/resolver.rb,
lib/ama-entity-mapper/type/attribute.rb,
lib/ama-entity-mapper/type/parameter.rb,
lib/ama-entity-mapper/type/aux/hash_tuple.rb,
lib/ama-entity-mapper/type/builtin/set_type.rb,
lib/ama-entity-mapper/type/builtin/hash_type.rb,
lib/ama-entity-mapper/type/builtin/array_type.rb,
lib/ama-entity-mapper/type/builtin/datetime_type.rb,
lib/ama-entity-mapper/type/builtin/rational_type.rb,
lib/ama-entity-mapper/type/builtin/primitive_type.rb,
lib/ama-entity-mapper/type/builtin/enumerable_type.rb,
lib/ama-entity-mapper/type/builtin/hash_tuple_type.rb,
lib/ama-entity-mapper/type/builtin/primitive_type/denormalizer.rb

Overview

Type wrapper

Defined Under Namespace

Modules: Aux, BuiltIn Classes: Analyzer, Any, Attribute, Parameter, Registry, Resolver

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Mixin::HandlerSupport

declare_handler_block_setter, declare_handler_getter, declare_handler_method, declare_handler_setter, declare_namespace_method, included

Methods included from Mixin::Reflection

#install_object_method, #method_object, #object_variable, #object_variable_exists, #object_variables, #set_object_attribute

Methods included from Mixin::Errors

#compliance_error, #mapping_error, #raise_if_internal, #validation_error

Constructor Details

#initialize(klass, virtual: false) ⇒ Type



62
63
64
65
66
67
# File 'lib/ama-entity-mapper/type.rb', line 62

def initialize(klass, virtual: false)
  @type = validate_type!(klass)
  @parameters = {}
  @attributes = {}
  @virtual = virtual
end

Instance Attribute Details

#attributesHash{Symbol, AMA::Entity::Mapper::Type::Attribute}



35
36
37
# File 'lib/ama-entity-mapper/type.rb', line 35

def attributes
  @attributes
end

#denormalizerAMA::Entity::Mapper::Handler::Entity::Denormalizer



50
# File 'lib/ama-entity-mapper/type.rb', line 50

handler :denormalizer, :denormalize

#enumeratorAMA::Entity::Mapper::Handler::Entity::Enumerator



53
# File 'lib/ama-entity-mapper/type.rb', line 53

handler :enumerator, :enumerate

#factoryAMA::Entity::Mapper::Handler::Entity::Factory



44
# File 'lib/ama-entity-mapper/type.rb', line 44

handler :factory, :create

#injectorAMA::Entity::Mapper::Handler::Entity::Validator



56
# File 'lib/ama-entity-mapper/type.rb', line 56

handler :injector, :inject

#normalizerAMA::Entity::Mapper::Handler::Entity::Normalizer



47
# File 'lib/ama-entity-mapper/type.rb', line 47

handler :normalizer, :normalize

#parametersHash{Symbol, AMA::Entity::Mapper::Type::Parameter}



32
33
34
# File 'lib/ama-entity-mapper/type.rb', line 32

def parameters
  @parameters
end

#typeClass



29
30
31
# File 'lib/ama-entity-mapper/type.rb', line 29

def type
  @type
end

#virtualTrueClass, FalseClass



38
39
40
# File 'lib/ama-entity-mapper/type.rb', line 38

def virtual
  @virtual
end

Instance Method Details

#==(other) ⇒ Object



179
180
181
# File 'lib/ama-entity-mapper/type.rb', line 179

def ==(other)
  eql?(other)
end

#attribute!(name, *types, **options) ⇒ Object

Shortcut for attribute creation.



101
102
103
104
105
106
107
108
109
110
# 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

#eql?(other) ⇒ Boolean



174
175
176
177
# 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

#hashObject



170
171
172
# File 'lib/ama-entity-mapper/type.rb', line 170

def hash
  @type.hash ^ @attributes.hash
end

#instance!(object, context) ⇒ Object



79
80
81
82
83
# 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

#instance?(object) ⇒ TrueClass, FalseClass

Tells if provided object is an instance of this type.

This doesn’t mean all of it’s attributes do match requested types.



75
76
77
# File 'lib/ama-entity-mapper/type.rb', line 75

def instance?(object)
  object.is_a?(@type)
end

#parameter!(id) ⇒ Parameter

Creates new type parameter



116
117
118
119
120
# 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

#resolve(parameters) ⇒ AMA::Entity::Mapper::Type



146
147
148
149
150
# File 'lib/ama-entity-mapper/type.rb', line 146

def resolve(parameters)
  parameters.reduce(self) do |carrier, tuple|
    carrier.resolve_parameter(*tuple)
  end
end

#resolve_parameter(parameter, substitution) ⇒ Object

Resolves single parameter type. Substitution may be either another parameter or array of types.



127
128
129
130
131
132
133
134
135
136
137
138
139
140
# 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

#resolved!(context = Context.new) ⇒ Object

Validates that type is fully resolved, otherwise raises an error



92
93
94
# File 'lib/ama-entity-mapper/type.rb', line 92

def resolved!(context = Context.new)
  attributes.values.each { |attribute| attribute.resolved!(context) }
end

#resolved?TrueClass, FalseClass



86
87
88
# File 'lib/ama-entity-mapper/type.rb', line 86

def resolved?
  attributes.values.all?(&:resolved?)
end

#to_defObject



191
192
193
194
195
196
197
198
199
200
# 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

#to_sObject



183
184
185
186
187
188
189
# 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

#valid!(object, context) ⇒ Object



162
163
164
165
166
167
168
# 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

#valid?(object, context) ⇒ Boolean



158
159
160
# File 'lib/ama-entity-mapper/type.rb', line 158

def valid?(object, context)
  violations(object, context).empty?
end

#violations(object, context) ⇒ Object

rubocop:enable Metrics/LineLength



154
155
156
# File 'lib/ama-entity-mapper/type.rb', line 154

def violations(object, context)
  validator.validate(object, self, context)
end