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.
- checksums.yaml +4 -4
- data/.rubocop.yml +23 -0
- data/.ruby-version +1 -0
- data/Appraisals +21 -0
- data/CHANGELOG.md +18 -1
- data/README.md +178 -126
- data/gemfiles/.bundle/config +2 -0
- data/gemfiles/no_railties_no_sidekiq.gemfile +16 -0
- data/gemfiles/no_railties_no_sidekiq.gemfile.lock +127 -0
- data/gemfiles/railties_6.gemfile +14 -0
- data/gemfiles/railties_6.gemfile.lock +253 -0
- data/gemfiles/railties_6_no_sidekiq.gemfile +17 -0
- data/gemfiles/railties_6_no_sidekiq.gemfile.lock +158 -0
- data/gemfiles/railties_6_sidekiq.gemfile +18 -0
- data/gemfiles/railties_6_sidekiq.gemfile.lock +167 -0
- data/gemfiles/railties_7_no_sidekiq.gemfile +17 -0
- data/gemfiles/railties_7_no_sidekiq.gemfile.lock +157 -0
- data/gemfiles/railties_7_sidekiq.gemfile +18 -0
- data/gemfiles/railties_7_sidekiq.gemfile.lock +166 -0
- data/lib/interactify/async_job_klass.rb +61 -0
- data/lib/interactify/call_wrapper.rb +2 -0
- data/lib/interactify/contract_failure.rb +6 -0
- data/lib/interactify/contract_helpers.rb +10 -10
- data/lib/interactify/dsl.rb +6 -2
- data/lib/interactify/each_chain.rb +12 -4
- data/lib/interactify/if_interactor.rb +10 -4
- data/lib/interactify/interactor_wiring/callable_representation.rb +79 -0
- data/lib/interactify/interactor_wiring/constants.rb +125 -0
- data/lib/interactify/interactor_wiring/error_context.rb +41 -0
- data/lib/interactify/interactor_wiring/files.rb +51 -0
- data/lib/interactify/interactor_wiring.rb +57 -272
- data/lib/interactify/interactor_wrapper.rb +72 -0
- data/lib/interactify/job_maker.rb +20 -69
- data/lib/interactify/jobable.rb +11 -7
- data/lib/interactify/mismatching_promise_error.rb +17 -0
- data/lib/interactify/null_job.rb +11 -0
- data/lib/interactify/organizer.rb +30 -0
- data/lib/interactify/promising.rb +34 -0
- data/lib/interactify/rspec/matchers.rb +9 -11
- data/lib/interactify/unique_klass_name.rb +21 -0
- data/lib/interactify/version.rb +1 -1
- data/lib/interactify.rb +96 -9
- metadata +36 -23
- data/lib/interactify/organizer_call_monkey_patch.rb +0 -40
@@ -1,5 +1,7 @@
|
|
1
|
-
|
2
|
-
|
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
|
17
|
-
@
|
18
|
+
def job_klass
|
19
|
+
@job_klass ||= define_job_klass
|
18
20
|
end
|
19
21
|
|
20
22
|
private
|
21
23
|
|
22
|
-
def
|
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
|
-
|
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(
|
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
|
-
|
46
|
-
|
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
|
data/lib/interactify/jobable.rb
CHANGED
@@ -1,4 +1,6 @@
|
|
1
|
-
|
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
|
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.
|
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.
|
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.
|
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,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
|
-
|
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
|
-
|
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
|
-
|
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
|
data/lib/interactify/version.rb
CHANGED
data/lib/interactify.rb
CHANGED
@@ -1,14 +1,60 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require 'active_support/all'
|
3
|
+
require "interactor"
|
4
|
+
require "interactor-contracts"
|
5
|
+
require "active_support/all"
|
7
6
|
|
8
|
-
require
|
9
|
-
require
|
10
|
-
require
|
11
|
-
require
|
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 ||=
|
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.
|
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-
|
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:
|
42
|
+
name: activesupport
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - ">="
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version:
|
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:
|
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:
|
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/
|
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:
|
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.
|
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
|