interactify 0.3.0.pre.RC1 → 0.4.0
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 +1 -0
- data/Appraisals +2 -0
- data/CHANGELOG.md +5 -0
- data/README.md +10 -4
- data/gemfiles/no_railties_no_sidekiq.gemfile +3 -1
- data/gemfiles/no_railties_no_sidekiq.gemfile.lock +1 -1
- data/gemfiles/railties_6_no_sidekiq.gemfile +3 -1
- data/gemfiles/railties_6_no_sidekiq.gemfile.lock +2 -1
- data/gemfiles/railties_6_sidekiq.gemfile +3 -1
- data/gemfiles/railties_6_sidekiq.gemfile.lock +2 -1
- data/gemfiles/railties_7_no_sidekiq.gemfile +3 -1
- data/gemfiles/railties_7_no_sidekiq.gemfile.lock +2 -1
- data/gemfiles/railties_7_sidekiq.gemfile +3 -1
- data/gemfiles/railties_7_sidekiq.gemfile.lock +2 -1
- data/lib/interactify/async/job_klass.rb +63 -0
- data/lib/interactify/async/job_maker.rb +58 -0
- data/lib/interactify/async/jobable.rb +96 -0
- data/lib/interactify/async/null_job.rb +23 -0
- data/lib/interactify/configuration.rb +15 -0
- data/lib/interactify/contracts/call_wrapper.rb +19 -0
- data/lib/interactify/contracts/failure.rb +8 -0
- data/lib/interactify/contracts/helpers.rb +81 -0
- data/lib/interactify/contracts/mismatching_promise_error.rb +19 -0
- data/lib/interactify/contracts/promising.rb +36 -0
- data/lib/interactify/contracts/setup.rb +39 -0
- data/lib/interactify/dsl/each_chain.rb +90 -0
- data/lib/interactify/dsl/if_interactor.rb +81 -0
- data/lib/interactify/dsl/if_klass.rb +82 -0
- data/lib/interactify/dsl/organizer.rb +32 -0
- data/lib/interactify/dsl/unique_klass_name.rb +23 -0
- data/lib/interactify/dsl/wrapper.rb +74 -0
- data/lib/interactify/dsl.rb +12 -6
- data/lib/interactify/rspec_matchers/matchers.rb +68 -0
- data/lib/interactify/version.rb +1 -1
- data/lib/interactify/{interactor_wiring → wiring}/callable_representation.rb +2 -2
- data/lib/interactify/{interactor_wiring → wiring}/constants.rb +1 -1
- data/lib/interactify/{interactor_wiring → wiring}/error_context.rb +1 -1
- data/lib/interactify/{interactor_wiring → wiring}/files.rb +1 -1
- data/lib/interactify/{interactor_wiring.rb → wiring.rb} +4 -4
- data/lib/interactify.rb +13 -50
- metadata +31 -56
- data/lib/interactify/async_job_klass.rb +0 -61
- data/lib/interactify/call_wrapper.rb +0 -17
- data/lib/interactify/contract_failure.rb +0 -6
- data/lib/interactify/contract_helpers.rb +0 -71
- data/lib/interactify/each_chain.rb +0 -88
- data/lib/interactify/if_interactor.rb +0 -70
- data/lib/interactify/interactor_wrapper.rb +0 -72
- data/lib/interactify/job_maker.rb +0 -56
- data/lib/interactify/jobable.rb +0 -94
- data/lib/interactify/mismatching_promise_error.rb +0 -17
- data/lib/interactify/null_job.rb +0 -11
- data/lib/interactify/organizer.rb +0 -30
- data/lib/interactify/promising.rb +0 -34
- data/lib/interactify/rspec/matchers.rb +0 -67
- data/lib/interactify/unique_klass_name.rb +0 -21
data/lib/interactify.rb
CHANGED
@@ -5,10 +5,11 @@ require "interactor-contracts"
|
|
5
5
|
require "active_support/all"
|
6
6
|
|
7
7
|
require "interactify/version"
|
8
|
-
require "interactify/
|
8
|
+
require "interactify/contracts/helpers"
|
9
|
+
require "interactify/contracts/promising"
|
9
10
|
require "interactify/dsl"
|
10
|
-
require "interactify/
|
11
|
-
require "interactify/
|
11
|
+
require "interactify/wiring"
|
12
|
+
require "interactify/configuration"
|
12
13
|
|
13
14
|
module Interactify
|
14
15
|
def self.railties_missing?
|
@@ -44,6 +45,11 @@ module Interactify
|
|
44
45
|
end
|
45
46
|
end
|
46
47
|
|
48
|
+
Interactify.instance_eval do
|
49
|
+
@sidekiq_missing = nil
|
50
|
+
@railties_missing = nil
|
51
|
+
end
|
52
|
+
|
47
53
|
begin
|
48
54
|
require "sidekiq"
|
49
55
|
rescue LoadError
|
@@ -51,7 +57,7 @@ rescue LoadError
|
|
51
57
|
end
|
52
58
|
|
53
59
|
begin
|
54
|
-
require
|
60
|
+
require "rails/railtie"
|
55
61
|
rescue LoadError
|
56
62
|
Interactify.railties_missing!
|
57
63
|
end
|
@@ -61,15 +67,7 @@ module Interactify
|
|
61
67
|
|
62
68
|
class << self
|
63
69
|
def validate_app(ignore: [])
|
64
|
-
Interactify::
|
65
|
-
end
|
66
|
-
|
67
|
-
def sidekiq_missing?
|
68
|
-
@sidekiq_missing
|
69
|
-
end
|
70
|
-
|
71
|
-
def sidekiq_missing!
|
72
|
-
@sidekiq_missing = true
|
70
|
+
Interactify::Wiring.new(root: Interactify.configuration.root, ignore:).validate_app
|
73
71
|
end
|
74
72
|
|
75
73
|
def reset
|
@@ -110,7 +108,7 @@ module Interactify
|
|
110
108
|
|
111
109
|
base.include Interactor::Organizer
|
112
110
|
base.include Interactor::Contracts
|
113
|
-
base.include Interactify::
|
111
|
+
base.include Interactify::Contracts::Helpers
|
114
112
|
|
115
113
|
# defines two classes on the receiver class
|
116
114
|
# the first is the job class
|
@@ -131,45 +129,10 @@ module Interactify
|
|
131
129
|
# that calls the interactor ExampleInteractor with (foo: 'bar')
|
132
130
|
#
|
133
131
|
# ExampleInteractor::Async.call(foo: 'bar')
|
134
|
-
include Interactify::Jobable
|
132
|
+
include Interactify::Async::Jobable
|
135
133
|
interactor_job
|
136
134
|
end
|
137
135
|
|
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
|
-
|
161
|
-
class Configuration
|
162
|
-
attr_writer :root
|
163
|
-
|
164
|
-
def root
|
165
|
-
@root ||= fallback
|
166
|
-
end
|
167
|
-
|
168
|
-
def fallback
|
169
|
-
Rails.root / "app" if Interactify.railties?
|
170
|
-
end
|
171
|
-
end
|
172
|
-
|
173
136
|
def called_klass_list
|
174
137
|
context._called.map(&:class)
|
175
138
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: interactify
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mark Burns
|
@@ -10,34 +10,6 @@ bindir: exe
|
|
10
10
|
cert_chain: []
|
11
11
|
date: 2023-12-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
-
- !ruby/object:Gem::Dependency
|
14
|
-
name: interactor
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - ">="
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: '0'
|
20
|
-
type: :runtime
|
21
|
-
prerelease: false
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
-
requirements:
|
24
|
-
- - ">="
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
version: '0'
|
27
|
-
- !ruby/object:Gem::Dependency
|
28
|
-
name: interactor-contracts
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
30
|
-
requirements:
|
31
|
-
- - ">="
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: '0'
|
34
|
-
type: :runtime
|
35
|
-
prerelease: false
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
37
|
-
requirements:
|
38
|
-
- - ">="
|
39
|
-
- !ruby/object:Gem::Version
|
40
|
-
version: '0'
|
41
13
|
- !ruby/object:Gem::Dependency
|
42
14
|
name: activesupport
|
43
15
|
requirement: !ruby/object:Gem::Requirement
|
@@ -53,13 +25,13 @@ dependencies:
|
|
53
25
|
- !ruby/object:Gem::Version
|
54
26
|
version: 6.0.0
|
55
27
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
28
|
+
name: interactor
|
57
29
|
requirement: !ruby/object:Gem::Requirement
|
58
30
|
requirements:
|
59
31
|
- - ">="
|
60
32
|
- !ruby/object:Gem::Version
|
61
33
|
version: '0'
|
62
|
-
type: :
|
34
|
+
type: :runtime
|
63
35
|
prerelease: false
|
64
36
|
version_requirements: !ruby/object:Gem::Requirement
|
65
37
|
requirements:
|
@@ -67,13 +39,13 @@ dependencies:
|
|
67
39
|
- !ruby/object:Gem::Version
|
68
40
|
version: '0'
|
69
41
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
42
|
+
name: interactor-contracts
|
71
43
|
requirement: !ruby/object:Gem::Requirement
|
72
44
|
requirements:
|
73
45
|
- - ">="
|
74
46
|
- !ruby/object:Gem::Version
|
75
47
|
version: '0'
|
76
|
-
type: :
|
48
|
+
type: :runtime
|
77
49
|
prerelease: false
|
78
50
|
version_requirements: !ruby/object:Gem::Requirement
|
79
51
|
requirements:
|
@@ -116,28 +88,31 @@ files:
|
|
116
88
|
- gemfiles/railties_7_sidekiq.gemfile
|
117
89
|
- gemfiles/railties_7_sidekiq.gemfile.lock
|
118
90
|
- lib/interactify.rb
|
119
|
-
- lib/interactify/
|
120
|
-
- lib/interactify/
|
121
|
-
- lib/interactify/
|
122
|
-
- lib/interactify/
|
91
|
+
- lib/interactify/async/job_klass.rb
|
92
|
+
- lib/interactify/async/job_maker.rb
|
93
|
+
- lib/interactify/async/jobable.rb
|
94
|
+
- lib/interactify/async/null_job.rb
|
95
|
+
- lib/interactify/configuration.rb
|
96
|
+
- lib/interactify/contracts/call_wrapper.rb
|
97
|
+
- lib/interactify/contracts/failure.rb
|
98
|
+
- lib/interactify/contracts/helpers.rb
|
99
|
+
- lib/interactify/contracts/mismatching_promise_error.rb
|
100
|
+
- lib/interactify/contracts/promising.rb
|
101
|
+
- lib/interactify/contracts/setup.rb
|
123
102
|
- lib/interactify/dsl.rb
|
124
|
-
- lib/interactify/each_chain.rb
|
125
|
-
- lib/interactify/if_interactor.rb
|
126
|
-
- lib/interactify/
|
127
|
-
- lib/interactify/
|
128
|
-
- lib/interactify/
|
129
|
-
- lib/interactify/
|
130
|
-
- lib/interactify/
|
131
|
-
- lib/interactify/interactor_wrapper.rb
|
132
|
-
- lib/interactify/job_maker.rb
|
133
|
-
- lib/interactify/jobable.rb
|
134
|
-
- lib/interactify/mismatching_promise_error.rb
|
135
|
-
- lib/interactify/null_job.rb
|
136
|
-
- lib/interactify/organizer.rb
|
137
|
-
- lib/interactify/promising.rb
|
138
|
-
- lib/interactify/rspec/matchers.rb
|
139
|
-
- lib/interactify/unique_klass_name.rb
|
103
|
+
- lib/interactify/dsl/each_chain.rb
|
104
|
+
- lib/interactify/dsl/if_interactor.rb
|
105
|
+
- lib/interactify/dsl/if_klass.rb
|
106
|
+
- lib/interactify/dsl/organizer.rb
|
107
|
+
- lib/interactify/dsl/unique_klass_name.rb
|
108
|
+
- lib/interactify/dsl/wrapper.rb
|
109
|
+
- lib/interactify/rspec_matchers/matchers.rb
|
140
110
|
- lib/interactify/version.rb
|
111
|
+
- lib/interactify/wiring.rb
|
112
|
+
- lib/interactify/wiring/callable_representation.rb
|
113
|
+
- lib/interactify/wiring/constants.rb
|
114
|
+
- lib/interactify/wiring/error_context.rb
|
115
|
+
- lib/interactify/wiring/files.rb
|
141
116
|
- sig/interactify.rbs
|
142
117
|
homepage: https://github.com/markburns/interactify
|
143
118
|
licenses:
|
@@ -156,12 +131,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
156
131
|
requirements:
|
157
132
|
- - ">="
|
158
133
|
- !ruby/object:Gem::Version
|
159
|
-
version:
|
134
|
+
version: 3.1.4
|
160
135
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
161
136
|
requirements:
|
162
|
-
- - "
|
137
|
+
- - ">="
|
163
138
|
- !ruby/object:Gem::Version
|
164
|
-
version:
|
139
|
+
version: '0'
|
165
140
|
requirements: []
|
166
141
|
rubygems_version: 3.3.26
|
167
142
|
signing_key:
|
@@ -1,61 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Interactify
|
4
|
-
class AsyncJobKlass
|
5
|
-
attr_reader :container_klass, :klass_suffix
|
6
|
-
|
7
|
-
def initialize(container_klass:, klass_suffix:)
|
8
|
-
@container_klass = container_klass
|
9
|
-
@klass_suffix = klass_suffix
|
10
|
-
end
|
11
|
-
|
12
|
-
def async_job_klass
|
13
|
-
klass = Class.new do
|
14
|
-
include Interactor
|
15
|
-
include Interactor::Contracts
|
16
|
-
end
|
17
|
-
|
18
|
-
attach_call(klass)
|
19
|
-
attach_call!(klass)
|
20
|
-
|
21
|
-
klass
|
22
|
-
end
|
23
|
-
|
24
|
-
def attach_call(async_job_klass)
|
25
|
-
# e.g. SomeInteractor::AsyncWithSuffix.call(foo: 'bar')
|
26
|
-
async_job_klass.send(:define_singleton_method, :call) do |context|
|
27
|
-
call!(context)
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
def attach_call!(async_job_klass)
|
32
|
-
this = self
|
33
|
-
|
34
|
-
# e.g. SomeInteractor::AsyncWithSuffix.call!(foo: 'bar')
|
35
|
-
async_job_klass.send(:define_singleton_method, :call!) do |context|
|
36
|
-
# e.g. SomeInteractor::JobWithSuffix
|
37
|
-
job_klass = this.container_klass.const_get("Job#{this.klass_suffix}")
|
38
|
-
|
39
|
-
# e.g. SomeInteractor::JobWithSuffix.perform_async({foo: 'bar'})
|
40
|
-
job_klass.perform_async(this.args(context))
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
def args(context)
|
45
|
-
args = context.to_h.stringify_keys
|
46
|
-
|
47
|
-
return args unless container_klass.respond_to?(:expected_keys)
|
48
|
-
|
49
|
-
restrict_to_optional_or_keys_from_contract(args)
|
50
|
-
end
|
51
|
-
|
52
|
-
def restrict_to_optional_or_keys_from_contract(args)
|
53
|
-
keys = container_klass.expected_keys.map(&:to_s)
|
54
|
-
|
55
|
-
optional = Array(container_klass.optional_attrs).map(&:to_s)
|
56
|
-
keys += optional
|
57
|
-
|
58
|
-
args.slice(*keys)
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|
@@ -1,17 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Interactify
|
4
|
-
module CallWrapper
|
5
|
-
# https://github.com/collectiveidea/interactor/blob/57b2af9a5a5afeb2c01059c40b792485cc21b052/lib/interactor.rb#L114
|
6
|
-
# Interactor#run calls Interactor#run!
|
7
|
-
# https://github.com/collectiveidea/interactor/blob/57b2af9a5a5afeb2c01059c40b792485cc21b052/lib/interactor.rb#L49
|
8
|
-
# Interactor.call calls Interactor.run
|
9
|
-
#
|
10
|
-
# The non bang methods call the bang methods and rescue
|
11
|
-
def run
|
12
|
-
@_interactor_called_by_non_bang_method = true
|
13
|
-
|
14
|
-
super
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
@@ -1,71 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "interactify/jobable"
|
4
|
-
require "interactify/call_wrapper"
|
5
|
-
require "interactify/organizer"
|
6
|
-
require "interactify/contract_failure"
|
7
|
-
|
8
|
-
module Interactify
|
9
|
-
module ContractHelpers
|
10
|
-
extend ActiveSupport::Concern
|
11
|
-
|
12
|
-
class_methods do
|
13
|
-
def expect(*attrs, filled: true)
|
14
|
-
expects do
|
15
|
-
attrs.each do |attr|
|
16
|
-
field = required(attr)
|
17
|
-
field.filled if filled
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
delegate(*attrs, to: :context)
|
22
|
-
end
|
23
|
-
|
24
|
-
def optional(*attrs)
|
25
|
-
@optional_attrs ||= []
|
26
|
-
@optional_attrs += attrs
|
27
|
-
|
28
|
-
delegate(*attrs, to: :context)
|
29
|
-
end
|
30
|
-
|
31
|
-
attr_reader :optional_attrs
|
32
|
-
|
33
|
-
def promise(*attrs, filled: true, should_delegate: true)
|
34
|
-
promises do
|
35
|
-
attrs.each do |attr|
|
36
|
-
field = required(attr)
|
37
|
-
field.filled if filled
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
delegate(*attrs, to: :context) if should_delegate
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
included do
|
46
|
-
c = Class.new(ContractFailure)
|
47
|
-
# example self is Whatever::SomeInteractor
|
48
|
-
# failure class: Whatever::SomeInteractor::InteractorContractFailure
|
49
|
-
const_set "InteractorContractFailure", c
|
50
|
-
prepend CallWrapper
|
51
|
-
include Organizer
|
52
|
-
|
53
|
-
on_breach do |breaches|
|
54
|
-
breaches = breaches.map { |b| { b.property => b.messages } }.inject(&:merge)
|
55
|
-
|
56
|
-
Interactify.trigger_contract_breach_hook(context, breaches)
|
57
|
-
|
58
|
-
if @_interactor_called_by_non_bang_method == true
|
59
|
-
context.fail! contract_failures: breaches
|
60
|
-
else
|
61
|
-
# e.g. raises
|
62
|
-
# SomeNamespace::SomeClass::ContractFailure, {whatever: 'is missing'}
|
63
|
-
# but also sending the context into Sentry
|
64
|
-
exception = c.new(breaches.to_json)
|
65
|
-
Interactify.trigger_before_raise_hook(exception)
|
66
|
-
raise exception
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|
@@ -1,88 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "interactify/unique_klass_name"
|
4
|
-
|
5
|
-
module Interactify
|
6
|
-
class EachChain
|
7
|
-
attr_reader :each_loop_klasses, :plural_resource_name, :evaluating_receiver
|
8
|
-
|
9
|
-
def self.attach_klass(evaluating_receiver, plural_resource_name, *each_loop_klasses)
|
10
|
-
iteratable = new(each_loop_klasses, plural_resource_name, evaluating_receiver)
|
11
|
-
iteratable.attach_klass
|
12
|
-
end
|
13
|
-
|
14
|
-
def initialize(each_loop_klasses, plural_resource_name, evaluating_receiver)
|
15
|
-
@each_loop_klasses = each_loop_klasses
|
16
|
-
@plural_resource_name = plural_resource_name
|
17
|
-
@evaluating_receiver = evaluating_receiver
|
18
|
-
end
|
19
|
-
|
20
|
-
# allows us to dynamically create an interactor chain
|
21
|
-
# that iterates over the packages and
|
22
|
-
# uses the passed in each_loop_klasses
|
23
|
-
# rubocop:disable all
|
24
|
-
def klass
|
25
|
-
this = self
|
26
|
-
|
27
|
-
Class.new do # class SomeNamespace::EachPackage
|
28
|
-
include Interactify # include Interactify
|
29
|
-
|
30
|
-
expects do # expects do
|
31
|
-
required(this.plural_resource_name) # required(:packages)
|
32
|
-
end # end
|
33
|
-
|
34
|
-
define_singleton_method(:source_location) do # def self.source_location
|
35
|
-
const_source_location this.evaluating_receiver.to_s # [file, line]
|
36
|
-
end # end
|
37
|
-
|
38
|
-
define_method(:run!) do # def run!
|
39
|
-
context.send(this.plural_resource_name).each_with_index do |resource, index|# context.packages.each_with_index do |package, index|
|
40
|
-
context[this.singular_resource_name] = resource # context.package = package
|
41
|
-
context[this.singular_resource_index_name] = index # context.package_index = index
|
42
|
-
|
43
|
-
klasses = InteractorWrapper.wrap_many(self, this.each_loop_klasses)
|
44
|
-
|
45
|
-
klasses.each do |interactor| # [A, B, C].each do |interactor|
|
46
|
-
interactor.call!(context) # interactor.call!(context)
|
47
|
-
end # end
|
48
|
-
end # end
|
49
|
-
|
50
|
-
context[this.singular_resource_name] = nil # context.package = nil
|
51
|
-
context[this.singular_resource_index_name] = nil # context.package_index = nil
|
52
|
-
|
53
|
-
context # context
|
54
|
-
end # end
|
55
|
-
|
56
|
-
define_method(:inspect) do
|
57
|
-
"<#{this.namespace}::#{this.iterator_klass_name} iterates_over: #{this.each_loop_klasses.inspect}>"
|
58
|
-
end
|
59
|
-
end
|
60
|
-
end
|
61
|
-
# rubocop:enable all
|
62
|
-
|
63
|
-
def attach_klass
|
64
|
-
name = iterator_klass_name
|
65
|
-
|
66
|
-
namespace.const_set(name, klass)
|
67
|
-
namespace.const_get(name)
|
68
|
-
end
|
69
|
-
|
70
|
-
def namespace
|
71
|
-
evaluating_receiver
|
72
|
-
end
|
73
|
-
|
74
|
-
def iterator_klass_name
|
75
|
-
prefix = "Each#{singular_resource_name.to_s.camelize}"
|
76
|
-
|
77
|
-
UniqueKlassName.for(namespace, prefix)
|
78
|
-
end
|
79
|
-
|
80
|
-
def singular_resource_name
|
81
|
-
plural_resource_name.to_s.singularize.to_sym
|
82
|
-
end
|
83
|
-
|
84
|
-
def singular_resource_index_name
|
85
|
-
"#{singular_resource_name}_index".to_sym
|
86
|
-
end
|
87
|
-
end
|
88
|
-
end
|
@@ -1,70 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "interactify/unique_klass_name"
|
4
|
-
|
5
|
-
module Interactify
|
6
|
-
class IfInteractor
|
7
|
-
attr_reader :condition, :success_interactor, :failure_interactor, :evaluating_receiver
|
8
|
-
|
9
|
-
def self.attach_klass(evaluating_receiver, condition, succcess_interactor, failure_interactor)
|
10
|
-
ifable = new(evaluating_receiver, condition, succcess_interactor, failure_interactor)
|
11
|
-
ifable.attach_klass
|
12
|
-
end
|
13
|
-
|
14
|
-
def initialize(evaluating_receiver, condition, succcess_interactor, failure_interactor)
|
15
|
-
@evaluating_receiver = evaluating_receiver
|
16
|
-
@condition = condition
|
17
|
-
@success_interactor = succcess_interactor
|
18
|
-
@failure_interactor = failure_interactor
|
19
|
-
end
|
20
|
-
|
21
|
-
# allows us to dynamically create an interactor chain
|
22
|
-
# that iterates over the packages and
|
23
|
-
# uses the passed in each_loop_klasses
|
24
|
-
# rubocop:disable all
|
25
|
-
def klass
|
26
|
-
this = self
|
27
|
-
|
28
|
-
Class.new do
|
29
|
-
include Interactor
|
30
|
-
include Interactor::Contracts
|
31
|
-
|
32
|
-
expects do
|
33
|
-
required(this.condition) unless this.condition.is_a?(Proc)
|
34
|
-
end
|
35
|
-
|
36
|
-
define_singleton_method(:source_location) do
|
37
|
-
const_source_location this.evaluating_receiver.to_s # [file, line]
|
38
|
-
end
|
39
|
-
|
40
|
-
define_method(:run!) do
|
41
|
-
result = this.condition.is_a?(Proc) ? this.condition.call(context) : context.send(this.condition)
|
42
|
-
interactor = result ? this.success_interactor : this.failure_interactor
|
43
|
-
interactor&.respond_to?(:call!) ? interactor.call!(context) : interactor&.call(context)
|
44
|
-
end
|
45
|
-
|
46
|
-
define_method(:inspect) do
|
47
|
-
"<#{this.namespace}::#{this.if_klass_name} #{this.condition} ? #{this.success_interactor} : #{this.failure_interactor}>"
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
51
|
-
# rubocop:enable all
|
52
|
-
|
53
|
-
def attach_klass
|
54
|
-
name = if_klass_name
|
55
|
-
namespace.const_set(name, klass)
|
56
|
-
namespace.const_get(name)
|
57
|
-
end
|
58
|
-
|
59
|
-
def namespace
|
60
|
-
evaluating_receiver
|
61
|
-
end
|
62
|
-
|
63
|
-
def if_klass_name
|
64
|
-
prefix = condition.is_a?(Proc) ? "Proc" : condition
|
65
|
-
prefix = "If#{prefix.to_s.camelize}"
|
66
|
-
|
67
|
-
UniqueKlassName.for(namespace, prefix)
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
@@ -1,72 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "interactify/unique_klass_name"
|
4
|
-
|
5
|
-
module Interactify
|
6
|
-
class InteractorWrapper
|
7
|
-
attr_reader :organizer, :interactor
|
8
|
-
|
9
|
-
def self.wrap_many(organizer, interactors)
|
10
|
-
Array(interactors).map do |interactor|
|
11
|
-
wrap(organizer, interactor)
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
def self.wrap(organizer, interactor)
|
16
|
-
new(organizer, interactor).wrap
|
17
|
-
end
|
18
|
-
|
19
|
-
def initialize(organizer, interactor)
|
20
|
-
@organizer = organizer
|
21
|
-
@interactor = interactor
|
22
|
-
end
|
23
|
-
|
24
|
-
def wrap
|
25
|
-
case interactor
|
26
|
-
when Hash
|
27
|
-
wrap_conditional
|
28
|
-
when Array
|
29
|
-
wrap_chain
|
30
|
-
when Proc
|
31
|
-
wrap_proc
|
32
|
-
else
|
33
|
-
interactor
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
def wrap_chain
|
38
|
-
return self.class.wrap(organizer, interactor.first) if interactor.length == 1
|
39
|
-
|
40
|
-
klass_name = UniqueKlassName.for(organizer, "Chained")
|
41
|
-
organizer.chain(klass_name, *interactor.map { self.class.wrap(organizer, _1) })
|
42
|
-
end
|
43
|
-
|
44
|
-
def wrap_conditional
|
45
|
-
raise ArgumentError, "Hash must have at least :if, and :then key" unless condition && then_do
|
46
|
-
|
47
|
-
return organizer.if(condition, then_do, else_do) if else_do
|
48
|
-
|
49
|
-
organizer.if(condition, then_do)
|
50
|
-
end
|
51
|
-
|
52
|
-
def condition = interactor[:if]
|
53
|
-
def then_do = interactor[:then]
|
54
|
-
def else_do = interactor[:else]
|
55
|
-
|
56
|
-
def wrap_proc
|
57
|
-
this = self
|
58
|
-
|
59
|
-
Class.new do
|
60
|
-
include Interactify
|
61
|
-
|
62
|
-
define_singleton_method :wrapped do
|
63
|
-
this.interactor
|
64
|
-
end
|
65
|
-
|
66
|
-
define_method(:call) do
|
67
|
-
this.interactor.call(context)
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|
@@ -1,56 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "interactify/async_job_klass"
|
4
|
-
require "interactify/null_job"
|
5
|
-
|
6
|
-
module Interactify
|
7
|
-
class JobMaker
|
8
|
-
attr_reader :opts, :method_name, :container_klass, :klass_suffix
|
9
|
-
|
10
|
-
def initialize(container_klass:, opts:, klass_suffix:, method_name: :call!)
|
11
|
-
@container_klass = container_klass
|
12
|
-
@opts = opts
|
13
|
-
@method_name = method_name
|
14
|
-
@klass_suffix = klass_suffix
|
15
|
-
end
|
16
|
-
|
17
|
-
concerning :JobClass do
|
18
|
-
def job_klass
|
19
|
-
@job_klass ||= define_job_klass
|
20
|
-
end
|
21
|
-
|
22
|
-
private
|
23
|
-
|
24
|
-
def define_job_klass
|
25
|
-
return NullJob if Interactify.sidekiq_missing?
|
26
|
-
|
27
|
-
this = self
|
28
|
-
|
29
|
-
invalid_keys = this.opts.symbolize_keys.keys - %i[queue retry dead backtrace pool tags]
|
30
|
-
|
31
|
-
raise ArgumentError, "Invalid keys: #{invalid_keys}" if invalid_keys.any?
|
32
|
-
|
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
|
41
|
-
include Sidekiq::Job
|
42
|
-
|
43
|
-
sidekiq_options(opts)
|
44
|
-
|
45
|
-
def perform(...)
|
46
|
-
self.class.module_parent.send(self.class::JOBABLE_METHOD_NAME, ...)
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
def async_job_klass
|
53
|
-
AsyncJobKlass.new(container_klass:, klass_suffix:).async_job_klass
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|