1
1
# frozen_string_literal: true
2
2
3
3
require "interactify/dsl/unique_klass_name"
4
+ require "interactify/dsl/if_klass"
4
5
5
6
module Interactify
6
7
module Dsl
7
8
class IfInteractor
8
- attr_reader :condition , :success_interactor , :failure_interactor , : evaluating_receiver
9
+ attr_reader :condition , :evaluating_receiver
9
10
10
11
def self . attach_klass ( evaluating_receiver , condition , succcess_interactor , failure_interactor )
11
12
ifable = new ( evaluating_receiver , condition , succcess_interactor , failure_interactor )
12
13
ifable . attach_klass
13
14
end
14
15
15
- def initialize ( evaluating_receiver , condition , succcess_interactor , failure_interactor )
16
+ def initialize ( evaluating_receiver , condition , succcess_arg , failure_arg )
16
17
@evaluating_receiver = evaluating_receiver
17
18
@condition = condition
18
- @success_interactor = succcess_interactor
19
- @failure_interactor = failure_interactor
19
+ @success_arg = succcess_arg
20
+ @failure_arg = failure_arg
21
+ end
22
+
23
+ def success_interactor
24
+ @success_interactor ||= build_chain ( @success_arg , true )
25
+ end
26
+
27
+ def failure_interactor
28
+ @failure_interactor ||= build_chain ( @failure_arg , false )
20
29
end
21
30
22
31
# allows us to dynamically create an interactor chain
23
32
# that iterates over the packages and
24
33
# uses the passed in each_loop_klasses
25
- # rubocop:disable all
26
34
def klass
27
- this = self
28
-
29
- Class . new do
30
- include Interactor
31
- include Interactor ::Contracts
32
-
33
- expects do
34
- required ( this . condition ) unless this . condition . is_a? ( Proc )
35
- end
36
-
37
- define_singleton_method ( :source_location ) do
38
- const_source_location this . evaluating_receiver . to_s # [file, line]
39
- end
40
-
41
- define_method ( :run! ) do
42
- result = this . condition . is_a? ( Proc ) ? this . condition . call ( context ) : context . send ( this . condition )
43
- interactor = result ? this . success_interactor : this . failure_interactor
44
- interactor &.respond_to? ( :call! ) ? interactor . call! ( context ) : interactor &.call ( context )
45
- end
35
+ IfKlass . new ( self ) . klass
36
+ end
46
37
47
- define_method ( :inspect ) do
48
- "<#{ this . namespace } ::#{ this . if_klass_name } #{ this . condition } ? #{ this . success_interactor } : #{ this . failure_interactor } >"
49
- end
38
+ # so we have something to attach subclasses to during building
39
+ # of the outer class, before we finalize the outer If class
40
+ def klass_basis
41
+ @klass_basis ||= Class . new do
42
+ include Interactify
50
43
end
51
44
end
52
- # rubocop:enable all
53
45
54
46
def attach_klass
55
47
name = if_klass_name
@@ -62,10 +54,27 @@ def namespace
62
54
end
63
55
64
56
def if_klass_name
65
- prefix = condition . is_a? ( Proc ) ? "Proc" : condition
66
- prefix = "If#{ prefix . to_s . camelize } "
57
+ @if_klass_name ||=
58
+ begin
59
+ prefix = condition . is_a? ( Proc ) ? "Proc" : condition
60
+ prefix = "If#{ prefix . to_s . camelize } "
61
+
62
+ UniqueKlassName . for ( namespace , prefix )
63
+ end
64
+ end
65
+
66
+ private
67
67
68
- UniqueKlassName . for ( namespace , prefix )
68
+ def build_chain ( arg , truthiness )
69
+ return if arg . nil?
70
+
71
+ case arg
72
+ when Array
73
+ name = "If#{ condition . to_s . camelize } #{ truthiness ? 'IsTruthy' : 'IsFalsey' } "
74
+ klass_basis . chain ( name , *arg )
75
+ else
76
+ arg
77
+ end
69
78
end
70
79
end
71
80
end
0 commit comments