interactify 0.1.0.pre.alpha.1 → 0.3.0.pre.RC1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +23 -0
  3. data/.ruby-version +1 -0
  4. data/Appraisals +21 -0
  5. data/CHANGELOG.md +18 -1
  6. data/README.md +178 -126
  7. data/gemfiles/.bundle/config +2 -0
  8. data/gemfiles/no_railties_no_sidekiq.gemfile +16 -0
  9. data/gemfiles/no_railties_no_sidekiq.gemfile.lock +127 -0
  10. data/gemfiles/railties_6.gemfile +14 -0
  11. data/gemfiles/railties_6.gemfile.lock +253 -0
  12. data/gemfiles/railties_6_no_sidekiq.gemfile +17 -0
  13. data/gemfiles/railties_6_no_sidekiq.gemfile.lock +158 -0
  14. data/gemfiles/railties_6_sidekiq.gemfile +18 -0
  15. data/gemfiles/railties_6_sidekiq.gemfile.lock +167 -0
  16. data/gemfiles/railties_7_no_sidekiq.gemfile +17 -0
  17. data/gemfiles/railties_7_no_sidekiq.gemfile.lock +157 -0
  18. data/gemfiles/railties_7_sidekiq.gemfile +18 -0
  19. data/gemfiles/railties_7_sidekiq.gemfile.lock +166 -0
  20. data/lib/interactify/async_job_klass.rb +61 -0
  21. data/lib/interactify/call_wrapper.rb +2 -0
  22. data/lib/interactify/contract_failure.rb +6 -0
  23. data/lib/interactify/contract_helpers.rb +10 -10
  24. data/lib/interactify/dsl.rb +6 -2
  25. data/lib/interactify/each_chain.rb +12 -4
  26. data/lib/interactify/if_interactor.rb +10 -4
  27. data/lib/interactify/interactor_wiring/callable_representation.rb +79 -0
  28. data/lib/interactify/interactor_wiring/constants.rb +125 -0
  29. data/lib/interactify/interactor_wiring/error_context.rb +41 -0
  30. data/lib/interactify/interactor_wiring/files.rb +51 -0
  31. data/lib/interactify/interactor_wiring.rb +57 -272
  32. data/lib/interactify/interactor_wrapper.rb +72 -0
  33. data/lib/interactify/job_maker.rb +20 -69
  34. data/lib/interactify/jobable.rb +11 -7
  35. data/lib/interactify/mismatching_promise_error.rb +17 -0
  36. data/lib/interactify/null_job.rb +11 -0
  37. data/lib/interactify/organizer.rb +30 -0
  38. data/lib/interactify/promising.rb +34 -0
  39. data/lib/interactify/rspec/matchers.rb +9 -11
  40. data/lib/interactify/unique_klass_name.rb +21 -0
  41. data/lib/interactify/version.rb +1 -1
  42. data/lib/interactify.rb +96 -9
  43. metadata +36 -23
  44. data/lib/interactify/organizer_call_monkey_patch.rb +0 -40
@@ -1,5 +1,7 @@
1
- require 'sidekiq'
2
- require 'sidekiq/job'
1
+ # frozen_string_literal: true
2
+
3
+ require "interactify/async_job_klass"
4
+ require "interactify/null_job"
3
5
 
4
6
  module Interactify
5
7
  class JobMaker
@@ -13,93 +15,42 @@ module Interactify
13
15
  end
14
16
 
15
17
  concerning :JobClass do
16
- def job_class
17
- @job_class ||= define_job_class
18
+ def job_klass
19
+ @job_klass ||= define_job_klass
18
20
  end
19
21
 
20
22
  private
21
23
 
22
- def define_job_class
24
+ def define_job_klass
25
+ return NullJob if Interactify.sidekiq_missing?
26
+
23
27
  this = self
24
28
 
25
29
  invalid_keys = this.opts.symbolize_keys.keys - %i[queue retry dead backtrace pool tags]
26
30
 
27
31
  raise ArgumentError, "Invalid keys: #{invalid_keys}" if invalid_keys.any?
28
32
 
29
- job_class = Class.new do
33
+ build_job_klass(opts).tap do |klass|
34
+ klass.const_set(:JOBABLE_OPTS, opts)
35
+ klass.const_set(:JOBABLE_METHOD_NAME, method_name)
36
+ end
37
+ end
38
+
39
+ def build_job_klass(opts)
40
+ Class.new do
30
41
  include Sidekiq::Job
31
42
 
32
- sidekiq_options(this.opts)
43
+ sidekiq_options(opts)
33
44
 
34
45
  def perform(...)
35
46
  self.class.module_parent.send(self.class::JOBABLE_METHOD_NAME, ...)
36
47
  end
37
48
  end
38
-
39
- job_class.const_set(:JOBABLE_OPTS, opts)
40
- job_class.const_set(:JOBABLE_METHOD_NAME, method_name)
41
- job_class
42
49
  end
43
50
  end
44
51
 
45
- concerning :AsyncJobClass do
46
- def async_job_class
47
- klass = Class.new do
48
- include Interactor
49
- include Interactor::Contracts
50
- end
51
-
52
- attach_call(klass)
53
- attach_call!(klass)
54
-
55
- klass
56
- end
57
-
58
- def args(context)
59
- args = context.to_h.stringify_keys
60
-
61
- return args unless container_klass.respond_to?(:contract)
62
-
63
- restrict_to_optional_or_keys_from_contract(args)
64
- end
65
-
66
- private
67
-
68
- def attach_call(async_job_class)
69
- # e.g. SomeInteractor::AsyncWithSuffix.call(foo: 'bar')
70
- async_job_class.send(:define_singleton_method, :call) do |context|
71
- call!(context)
72
- end
73
- end
74
-
75
- def attach_call!(async_job_class)
76
- this = self
77
-
78
- # e.g. SomeInteractor::AsyncWithSuffix.call!(foo: 'bar')
79
- async_job_class.send(:define_singleton_method, :call!) do |context|
80
- # e.g. SomeInteractor::JobWithSuffix
81
- job_klass = this.container_klass.const_get("Job#{this.klass_suffix}")
82
-
83
- # e.g. SomeInteractor::JobWithSuffix.perform_async({foo: 'bar'})
84
- job_klass.perform_async(this.args(context))
85
- end
86
- end
87
-
88
- def restrict_to_optional_or_keys_from_contract(args)
89
- keys = container_klass
90
- .contract
91
- .expectations
92
- .instance_eval { @terms }
93
- .schema
94
- .key_map
95
- .to_dot_notation
96
- .map(&:to_s)
97
-
98
- optional = Array(container_klass.optional_attrs).map(&:to_s)
99
- keys += optional
100
-
101
- args.slice(*keys)
102
- end
52
+ def async_job_klass
53
+ AsyncJobKlass.new(container_klass:, klass_suffix:).async_job_klass
103
54
  end
104
55
  end
105
56
  end
@@ -1,4 +1,6 @@
1
- require 'interactify/job_maker'
1
+ # frozen_string_literal: true
2
+
3
+ require "interactify/job_maker"
2
4
 
3
5
  module Interactify
4
6
  module Jobable
@@ -9,6 +11,8 @@ module Interactify
9
11
  #
10
12
  # then let's make sure to define Klass::Job separately
11
13
  included do |base|
14
+ next if Interactify.sidekiq_missing?
15
+
12
16
  def base.inherited(klass)
13
17
  super_klass = klass.superclass
14
18
  super_job = super_klass::Job # really spiffing
@@ -18,7 +22,7 @@ module Interactify
18
22
 
19
23
  to_call = defined?(super_klass::Async) ? :interactor_job : :job_calling
20
24
 
21
- klass.send(to_call, opts: opts, method_name: jobable_method_name)
25
+ klass.send(to_call, opts:, method_name: jobable_method_name)
22
26
  super(klass)
23
27
  end
24
28
  end
@@ -51,18 +55,18 @@ module Interactify
51
55
  # obviously you will need to be aware that later interactors
52
56
  # in an interactor chain cannot depend on the result of the async
53
57
  # interactor
54
- def interactor_job(method_name: :call!, opts: {}, klass_suffix: '')
58
+ def interactor_job(method_name: :call!, opts: {}, klass_suffix: "")
55
59
  job_maker = JobMaker.new(container_klass: self, opts:, method_name:, klass_suffix:)
56
60
  # with WhateverInteractor::Job you can perform the interactor as a job
57
61
  # from sidekiq
58
62
  # e.g. WhateverInteractor::Job.perform_async(...)
59
- const_set("Job#{klass_suffix}", job_maker.job_class)
63
+ const_set("Job#{klass_suffix}", job_maker.job_klass)
60
64
 
61
65
  # with WhateverInteractor::Async you can call WhateverInteractor::Job
62
66
  # in an organizer oro on its oen using normal interactor call call! semantics
63
67
  # e.g. WhateverInteractor::Async.call(...)
64
68
  # WhateverInteractor::Async.call!(...)
65
- const_set("Async#{klass_suffix}", job_maker.async_job_class)
69
+ const_set("Async#{klass_suffix}", job_maker.async_job_klass)
66
70
  end
67
71
 
68
72
  # if this was defined in ExampleClass this creates the following class
@@ -80,10 +84,10 @@ module Interactify
80
84
  # # the following class is created that you can use to enqueue a job
81
85
  # in the sidekiq yaml file
82
86
  # ExampleClass::Job.some_method
83
- def job_calling(method_name:, opts: {}, klass_suffix: '')
87
+ def job_calling(method_name:, opts: {}, klass_suffix: "")
84
88
  job_maker = JobMaker.new(container_klass: self, opts:, method_name:, klass_suffix:)
85
89
 
86
- const_set("Job#{klass_suffix}", job_maker.job_class)
90
+ const_set("Job#{klass_suffix}", job_maker.job_klass)
87
91
  end
88
92
  end
89
93
  end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "interactify/contract_failure"
4
+
5
+ module Interactify
6
+ class MismatchingPromiseError < ContractFailure
7
+ def initialize(interactor, promising, promised_keys)
8
+ super <<~MESSAGE.chomp
9
+ #{interactor} does not promise:
10
+ #{promising.inspect}
11
+
12
+ Actual promises are:
13
+ #{promised_keys.inspect}
14
+ MESSAGE
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,11 @@
1
+ module Interactify
2
+ class NullJob
3
+ def method_missing(...)
4
+ self
5
+ end
6
+
7
+ def self.method_missing(...)
8
+ self
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "interactify/interactor_wrapper"
4
+
5
+ module Interactify
6
+ module Organizer
7
+ extend ActiveSupport::Concern
8
+
9
+ class_methods do
10
+ def organize(*interactors)
11
+ wrapped = InteractorWrapper.wrap_many(self, interactors)
12
+
13
+ super(*wrapped)
14
+ end
15
+ end
16
+
17
+ def call
18
+ self.class.organized.each do |interactor|
19
+ instance = interactor.new(context)
20
+
21
+ instance.instance_variable_set(
22
+ :@_interactor_called_by_non_bang_method,
23
+ @_interactor_called_by_non_bang_method
24
+ )
25
+
26
+ instance.tap(&:run!)
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "interactify/mismatching_promise_error"
4
+
5
+ module Interactify
6
+ class Promising
7
+ attr_reader :interactor, :promising
8
+
9
+ def self.validate(interactor, *promising)
10
+ new(interactor, *promising).validate
11
+
12
+ interactor
13
+ end
14
+
15
+ def initialize(interactor, *promising)
16
+ @interactor = interactor
17
+ @promising = format_keys promising
18
+ end
19
+
20
+ def validate
21
+ return if promising == promised_keys
22
+
23
+ raise MismatchingPromiseError.new(interactor, promising, promised_keys)
24
+ end
25
+
26
+ def promised_keys
27
+ format_keys interactor.promised_keys
28
+ end
29
+
30
+ def format_keys(keys)
31
+ Array(keys).compact.map(&:to_sym).sort
32
+ end
33
+ end
34
+ end
@@ -1,4 +1,6 @@
1
- require 'interactify/interactor_wiring'
1
+ # frozen_string_literal: true
2
+
3
+ require "interactify/interactor_wiring"
2
4
 
3
5
  # Custom matcher that implements expect_inputs
4
6
  # e.g.
@@ -6,7 +8,9 @@ require 'interactify/interactor_wiring'
6
8
 
7
9
  RSpec::Matchers.define :expect_inputs do |*expected_inputs|
8
10
  match do |actual|
9
- actual_inputs = expected_keys(actual)
11
+ next false unless actual.respond_to?(:expected_keys)
12
+
13
+ actual_inputs = Array(actual.expected_keys)
10
14
  @missing_inputs = expected_inputs - actual_inputs
11
15
  @extra_inputs = actual_inputs - expected_inputs
12
16
 
@@ -19,17 +23,15 @@ RSpec::Matchers.define :expect_inputs do |*expected_inputs|
19
23
  message += "\n\textra inputs: #{@extra_inputs}" if @extra_inputs
20
24
  message
21
25
  end
22
-
23
- def expected_keys(klass)
24
- Array(klass.contract.expectations.instance_eval { @terms }.json&.rules&.keys)
25
- end
26
26
  end
27
27
 
28
28
  # Custom matcher that implements promise_outputs
29
29
  # e.g. expect(described_class).to promise_outputs(:request_logger)
30
30
  RSpec::Matchers.define :promise_outputs do |*expected_outputs|
31
31
  match do |actual|
32
- actual_outputs = promised_keys(actual)
32
+ next false unless actual.respond_to?(:promised_keys)
33
+
34
+ actual_outputs = Array(actual.promised_keys)
33
35
  @missing_outputs = expected_outputs - actual_outputs
34
36
  @extra_outputs = actual_outputs - expected_outputs
35
37
 
@@ -42,10 +44,6 @@ RSpec::Matchers.define :promise_outputs do |*expected_outputs|
42
44
  message += "\n\textra outputs: #{@extra_outputs}" if @extra_outputs
43
45
  message
44
46
  end
45
-
46
- def promised_keys(klass)
47
- Array(klass.contract.promises.instance_eval { @terms }.json&.rules&.keys)
48
- end
49
47
  end
50
48
 
51
49
  # Custom matcher that implements organize_interactors
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Interactify
4
+ module UniqueKlassName
5
+ def self.for(namespace, prefix)
6
+ id = generate_unique_id
7
+ klass_name = :"#{prefix}#{id}"
8
+
9
+ while namespace.const_defined?(klass_name)
10
+ id = generate_unique_id
11
+ klass_name = :"#{prefix}#{id}"
12
+ end
13
+
14
+ klass_name.to_sym
15
+ end
16
+
17
+ def self.generate_unique_id
18
+ rand(10_000)
19
+ end
20
+ end
21
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Interactify
4
- VERSION = '0.1.0-alpha.1'
4
+ VERSION = "0.3.0-RC1"
5
5
  end
data/lib/interactify.rb CHANGED
@@ -1,14 +1,60 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'interactor'
4
- require 'interactor-contracts'
5
- require 'rails'
6
- require 'active_support/all'
3
+ require "interactor"
4
+ require "interactor-contracts"
5
+ require "active_support/all"
7
6
 
8
- require 'interactify/version'
9
- require 'interactify/contract_helpers'
10
- require 'interactify/dsl'
11
- require 'interactify/interactor_wiring'
7
+ require "interactify/version"
8
+ require "interactify/contract_helpers"
9
+ require "interactify/dsl"
10
+ require "interactify/interactor_wiring"
11
+ require "interactify/promising"
12
+
13
+ module Interactify
14
+ def self.railties_missing?
15
+ @railties_missing
16
+ end
17
+
18
+ def self.railties_missing!
19
+ @railties_missing = true
20
+ end
21
+
22
+ def self.railties
23
+ railties?
24
+ end
25
+
26
+ def self.railties?
27
+ !railties_missing?
28
+ end
29
+
30
+ def self.sidekiq_missing?
31
+ @sidekiq_missing
32
+ end
33
+
34
+ def self.sidekiq_missing!
35
+ @sidekiq_missing = true
36
+ end
37
+
38
+ def self.sidekiq
39
+ sidekiq?
40
+ end
41
+
42
+ def self.sidekiq?
43
+ !sidekiq_missing?
44
+ end
45
+ end
46
+
47
+ begin
48
+ require "sidekiq"
49
+ rescue LoadError
50
+ Interactify.sidekiq_missing!
51
+ end
52
+
53
+ begin
54
+ require 'rails/railtie'
55
+ rescue LoadError
56
+ Interactify.railties_missing!
57
+ end
12
58
 
13
59
  module Interactify
14
60
  extend ActiveSupport::Concern
@@ -18,6 +64,20 @@ module Interactify
18
64
  Interactify::InteractorWiring.new(root: Interactify.configuration.root, ignore:).validate_app
19
65
  end
20
66
 
67
+ def sidekiq_missing?
68
+ @sidekiq_missing
69
+ end
70
+
71
+ def sidekiq_missing!
72
+ @sidekiq_missing = true
73
+ end
74
+
75
+ def reset
76
+ @on_contract_breach = nil
77
+ @before_raise_hook = nil
78
+ @configuration = nil
79
+ end
80
+
21
81
  def trigger_contract_breach_hook(...)
22
82
  @on_contract_breach&.call(...)
23
83
  end
@@ -75,11 +135,38 @@ module Interactify
75
135
  interactor_job
76
136
  end
77
137
 
138
+ class_methods do
139
+ def promising(*args)
140
+ Promising.validate(self, *args)
141
+ end
142
+
143
+ def promised_keys
144
+ _interactify_extract_keys(contract.promises)
145
+ end
146
+
147
+ def expected_keys
148
+ _interactify_extract_keys(contract.expectations)
149
+ end
150
+
151
+ private
152
+
153
+ # this is the most brittle part of the code, relying on
154
+ # interactor-contracts internals
155
+ # so extracted it to here so change is isolated
156
+ def _interactify_extract_keys(clauses)
157
+ clauses.instance_eval { @terms }.json&.rules&.keys
158
+ end
159
+ end
160
+
78
161
  class Configuration
79
162
  attr_writer :root
80
163
 
81
164
  def root
82
- @root ||= Rails.root / 'app'
165
+ @root ||= fallback
166
+ end
167
+
168
+ def fallback
169
+ Rails.root / "app" if Interactify.railties?
83
170
  end
84
171
  end
85
172
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: interactify
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0.pre.alpha.1
4
+ version: 0.3.0.pre.RC1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mark Burns
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-12-26 00:00:00.000000000 Z
11
+ date: 2023-12-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: interactor
@@ -39,33 +39,19 @@ dependencies:
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
- name: rails
42
+ name: activesupport
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - ">="
46
46
  - !ruby/object:Gem::Version
47
- version: '0'
47
+ version: 6.0.0
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
- version: '0'
55
- - !ruby/object:Gem::Dependency
56
- name: sidekiq
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - ">="
60
- - !ruby/object:Gem::Version
61
- version: '0'
62
- type: :runtime
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - ">="
67
- - !ruby/object:Gem::Version
68
- version: '0'
54
+ version: 6.0.0
69
55
  - !ruby/object:Gem::Dependency
70
56
  name: debug
71
57
  requirement: !ruby/object:Gem::Requirement
@@ -81,7 +67,7 @@ dependencies:
81
67
  - !ruby/object:Gem::Version
82
68
  version: '0'
83
69
  - !ruby/object:Gem::Dependency
84
- name: deep_matching
70
+ name: appraisal
85
71
  requirement: !ruby/object:Gem::Requirement
86
72
  requirements:
87
73
  - - ">="
@@ -109,21 +95,48 @@ extensions: []
109
95
  extra_rdoc_files: []
110
96
  files:
111
97
  - ".rspec"
98
+ - ".rubocop.yml"
99
+ - ".ruby-version"
100
+ - Appraisals
112
101
  - CHANGELOG.md
113
102
  - LICENSE.txt
114
103
  - README.md
115
104
  - Rakefile
105
+ - gemfiles/.bundle/config
106
+ - gemfiles/no_railties_no_sidekiq.gemfile
107
+ - gemfiles/no_railties_no_sidekiq.gemfile.lock
108
+ - gemfiles/railties_6.gemfile
109
+ - gemfiles/railties_6.gemfile.lock
110
+ - gemfiles/railties_6_no_sidekiq.gemfile
111
+ - gemfiles/railties_6_no_sidekiq.gemfile.lock
112
+ - gemfiles/railties_6_sidekiq.gemfile
113
+ - gemfiles/railties_6_sidekiq.gemfile.lock
114
+ - gemfiles/railties_7_no_sidekiq.gemfile
115
+ - gemfiles/railties_7_no_sidekiq.gemfile.lock
116
+ - gemfiles/railties_7_sidekiq.gemfile
117
+ - gemfiles/railties_7_sidekiq.gemfile.lock
116
118
  - lib/interactify.rb
119
+ - lib/interactify/async_job_klass.rb
117
120
  - lib/interactify/call_wrapper.rb
121
+ - lib/interactify/contract_failure.rb
118
122
  - lib/interactify/contract_helpers.rb
119
123
  - lib/interactify/dsl.rb
120
124
  - lib/interactify/each_chain.rb
121
125
  - lib/interactify/if_interactor.rb
122
126
  - lib/interactify/interactor_wiring.rb
127
+ - lib/interactify/interactor_wiring/callable_representation.rb
128
+ - lib/interactify/interactor_wiring/constants.rb
129
+ - lib/interactify/interactor_wiring/error_context.rb
130
+ - lib/interactify/interactor_wiring/files.rb
131
+ - lib/interactify/interactor_wrapper.rb
123
132
  - lib/interactify/job_maker.rb
124
133
  - lib/interactify/jobable.rb
125
- - lib/interactify/organizer_call_monkey_patch.rb
134
+ - lib/interactify/mismatching_promise_error.rb
135
+ - lib/interactify/null_job.rb
136
+ - lib/interactify/organizer.rb
137
+ - lib/interactify/promising.rb
126
138
  - lib/interactify/rspec/matchers.rb
139
+ - lib/interactify/unique_klass_name.rb
127
140
  - lib/interactify/version.rb
128
141
  - sig/interactify.rbs
129
142
  homepage: https://github.com/markburns/interactify
@@ -143,14 +156,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
143
156
  requirements:
144
157
  - - ">="
145
158
  - !ruby/object:Gem::Version
146
- version: '3.2'
159
+ version: 2.7.8
147
160
  required_rubygems_version: !ruby/object:Gem::Requirement
148
161
  requirements:
149
162
  - - ">"
150
163
  - !ruby/object:Gem::Version
151
164
  version: 1.3.1
152
165
  requirements: []
153
- rubygems_version: 3.4.19
166
+ rubygems_version: 3.3.26
154
167
  signing_key:
155
168
  specification_version: 4
156
169
  summary: Interactors with bells and whistles
@@ -1,40 +0,0 @@
1
- module Interactify
2
- module OrganizerCallMonkeyPatch
3
- extend ActiveSupport::Concern
4
-
5
- class_methods do
6
- def organize(*interactors)
7
- wrapped = wrap_lambdas_in_interactors(interactors)
8
-
9
- super(*wrapped)
10
- end
11
-
12
- def wrap_lambdas_in_interactors(interactors)
13
- Array(interactors).map do |interactor|
14
- case interactor
15
- when Proc
16
- Class.new do
17
- include Interactify
18
-
19
- define_method(:call) do
20
- interactor.call(context)
21
- end
22
- end
23
- else
24
- interactor
25
- end
26
- end
27
- end
28
- end
29
-
30
- def call
31
- self.class.organized.each do |interactor|
32
- instance = interactor.new(context)
33
- instance.instance_variable_set(:@_interactor_called_by_non_bang_method,
34
- @_interactor_called_by_non_bang_method)
35
-
36
- instance.tap(&:run!)
37
- end
38
- end
39
- end
40
- end