Injector.inject()   A
last analyzed

Complexity

Conditions 2

Size

Total Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 5
rs 9.4285
cc 2
1
# frozen_string_literal: true
2
3
require_relative '../../mixin/reflection'
4
require_relative '../../mixin/errors'
5
6
module AMA
7
  module Entity
8
    class Mapper
9
      module Handler
10
        module Entity
11
          # Default attribute injector
12
          class Injector
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::Type::Attribute] attribute
20
            # @param [Object] value
21
            # @param [AMA::Entity::Mapper::Context] _context
22
            def inject(entity, _type, attribute, value, _context = nil)
23
              return entity if attribute.virtual
24
              set_object_attribute(entity, attribute.name, value)
25
              entity
26
            end
27
28
            class << self
29
              include Mixin::Reflection
30
31
              # @param [Injector] implementation
32
              # @return [Injector]
33
              def wrap(implementation)
34
                handler = handler_factory(implementation, INSTANCE)
35
                description = "Safety wrapper for #{implementation}"
36
                wrapper = method_object(:inject, to_s: description, &handler)
37
                wrapper.singleton_class.instance_eval do
38
                  include Mixin::Errors
39
                end
40
                wrapper
41
              end
42
43
              private
44
45
              # @param [Injector] impl
46
              # @param [Injector] fallback
47
              # @return [Injector]
48
              def handler_factory(impl, fallback)
49
                lambda do |entity, type, attr, val, ctx|
50
                  begin
51
                    impl.inject(entity, type, attr, val, ctx) do |e, t, a, v, c|
52
                      fallback.inject(e, t, a, v, c)
53
                    end
54
                  rescue StandardError => e
55
                    raise_if_internal(e)
56
                    message = "Unexpected error from injector #{impl}"
57
                    signature = '(entity, type, attr, val, ctx)'
58
                    options = { parent: e, context: ctx, signature: signature }
59
                    compliance_error(message, options)
60
                  end
61
                end
62
              end
63
            end
64
          end
65
        end
66
      end
67
    end
68
  end
69
end
70