Enumerator.handler_factory()   A
last analyzed

Complexity

Conditions 1

Size

Total Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 16
rs 9.4285
cc 1
1
# frozen_string_literal: true
2
3
require_relative '../../mixin/reflection'
4
require_relative '../../path/segment'
5
6
module AMA
7
  module Entity
8
    class Mapper
9
      module Handler
10
        module Entity
11
          # Default attribute enumerator
12
          class Enumerator
13
            include Mixin::Reflection
14
15
            INSTANCE = new
16
17
            # @param [Object] entity
18
            # @param [AMA::Entity::Mapper::Type] type
19
            # @param [AMA::Entity::Mapper::Context] _context
20
            def enumerate(entity, type, _context)
21
              ::Enumerator.new do |yielder|
22
                type.attributes.values.each do |attribute|
23
                  next if attribute.virtual
24
                  value = attribute.default
25
                  if object_variable_exists(entity, attribute.name)
26
                    value = object_variable(entity, attribute.name)
27
                  end
28
                  segment = Path::Segment.attribute(attribute.name)
29
                  yielder << [attribute, value, segment]
30
                end
31
              end
32
            end
33
34
            class << self
35
              include Mixin::Reflection
36
37
              # @param [Enumerator] implementation
38
              # @return [Enumerator]
39
              def wrap(implementation)
40
                handler = handler_factory(implementation, INSTANCE)
41
                description = "Safety wrapper for #{implementation}"
42
                wrapper = method_object(:enumerate, to_s: description, &handler)
43
                wrapper.singleton_class.instance_eval do
44
                  include Mixin::Errors
45
                end
46
                wrapper
47
              end
48
49
              private
50
51
              # @param [Enumerator] implementation
52
              # @param [Enumerator] fallback
53
              # @return [Enumerator]
54
              def handler_factory(implementation, fallback)
55
                lambda do |entity, type, ctx|
56
                  begin
57
                    implementation.enumerate(entity, type, ctx) do |e, t, c|
58
                      fallback.enumerate(e, t, c)
59
                    end
60
                  rescue StandardError => e
61
                    raise_if_internal(e)
62
                    message = 'Unexpected error from enumerator ' \
63
                      "#{implementation}"
64
                    signature = '(entity, type, context)'
65
                    options = { parent: e, context: ctx, signature: signature }
66
                    compliance_error(message, **options)
67
                  end
68
                end
69
              end
70
            end
71
          end
72
        end
73
      end
74
    end
75
  end
76
end
77