ii_interactor 1.1.0 → 2.1.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/.github/workflows/ci.yml +11 -3
- data/.gitignore +1 -0
- data/CHANGELOG.md +19 -0
- data/README.md +73 -173
- data/gemfiles/rails70.gemfile +5 -0
- data/ii_interactor.gemspec +1 -0
- data/lib/ii_interactor/base.rb +5 -5
- data/lib/ii_interactor/callbacks.rb +19 -0
- data/lib/ii_interactor/coactors.rb +23 -0
- data/lib/ii_interactor/config.rb +1 -0
- data/lib/ii_interactor/context.rb +27 -13
- data/lib/ii_interactor/contextualizer.rb +28 -0
- data/lib/ii_interactor/core.rb +25 -19
- data/lib/ii_interactor/errors.rb +3 -0
- data/lib/ii_interactor/instrumentation.rb +5 -0
- data/lib/ii_interactor/log_subscriber.rb +9 -0
- data/lib/ii_interactor/version.rb +1 -1
- data/lib/ii_interactor.rb +1 -5
- metadata +20 -9
- data/lib/ii_interactor/interaction.rb +0 -43
- data/lib/ii_interactor/loader.rb +0 -19
- data/lib/ii_interactor/lookup.rb +0 -66
- data/lib/ii_interactor/lookups/base.rb +0 -20
- data/lib/ii_interactor/lookups/name.rb +0 -20
- data/lib/ii_interactor/lookups/object.rb +0 -40
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f27fe194dd295f5882f0533132588686a9fead26c638f86db95b8b66979553bf
|
4
|
+
data.tar.gz: '08c3c2fbd0687fb42077215abb8edd0e85a76eda538c418fa5f869f50957ed90'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ab6289235d21d6085ce7b20d123efd152d1e387f6d17a708a107e735f259036bb87be8533e9e7e5b07613cc9ca14fd0b699521bbb1c6f42c855054884f0e690e
|
7
|
+
data.tar.gz: 76c6d853fc4ef5b6103d9dda4cdac6ecb9179b0b21c6b35e72519dd2059bb1efb95a431ae23dca207f51a78e8a8e598c56028851842b98b6a4181221da725f76
|
data/.github/workflows/ci.yml
CHANGED
@@ -4,21 +4,29 @@ on: [push, pull_request]
|
|
4
4
|
|
5
5
|
jobs:
|
6
6
|
test:
|
7
|
-
runs-on: ubuntu-
|
7
|
+
runs-on: ubuntu-20.04
|
8
8
|
strategy:
|
9
9
|
fail-fast: false
|
10
10
|
matrix:
|
11
|
-
ruby: [2.3, 2.4, 2.5, 2.6, 2.7, 3.0]
|
12
|
-
gemfile: ['rails50', 'rails51', 'rails52', 'rails60', 'rails61']
|
11
|
+
ruby: [2.3, 2.4, 2.5, 2.6, 2.7, '3.0']
|
12
|
+
gemfile: ['rails50', 'rails51', 'rails52', 'rails60', 'rails61', 'rails70']
|
13
13
|
exclude:
|
14
14
|
- ruby: 2.3
|
15
15
|
gemfile: rails60
|
16
16
|
- ruby: 2.3
|
17
17
|
gemfile: rails61
|
18
|
+
- ruby: 2.3
|
19
|
+
gemfile: rails70
|
18
20
|
- ruby: 2.4
|
19
21
|
gemfile: rails60
|
20
22
|
- ruby: 2.4
|
21
23
|
gemfile: rails61
|
24
|
+
- ruby: 2.4
|
25
|
+
gemfile: rails70
|
26
|
+
- ruby: 2.5
|
27
|
+
gemfile: rails70
|
28
|
+
- ruby: 2.6
|
29
|
+
gemfile: rails70
|
22
30
|
- ruby: 3.0
|
23
31
|
gemfile: rails50
|
24
32
|
- ruby: 3.0
|
data/.gitignore
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,24 @@
|
|
1
1
|
# CHANGELOG
|
2
2
|
|
3
|
+
## 2.1.0
|
4
|
+
|
5
|
+
* Add traversal config.
|
6
|
+
* Add callbacks for `call_all`.
|
7
|
+
* Add calling instrumentation.
|
8
|
+
* Bump coactive version to 0.2.
|
9
|
+
|
10
|
+
## 2.0.0
|
11
|
+
|
12
|
+
* Replace interaction feature with coactive.
|
13
|
+
|
14
|
+
## 1.2.0
|
15
|
+
|
16
|
+
* Add variable setting feature.
|
17
|
+
|
18
|
+
## 1.1.1
|
19
|
+
|
20
|
+
* Check `config.eager_load` instead of `Rails.env` before file loading.
|
21
|
+
|
3
22
|
## 1.1.0
|
4
23
|
|
5
24
|
* Add log subscriber.
|
data/README.md
CHANGED
@@ -27,6 +27,9 @@ Create interactor with `call` method and call it as follows:
|
|
27
27
|
|
28
28
|
```ruby
|
29
29
|
class Interactor < IIInteractor::Base
|
30
|
+
context_in :message
|
31
|
+
context_out :result
|
32
|
+
|
30
33
|
def call
|
31
34
|
@context.result = "called by #{@context.message}"
|
32
35
|
end
|
@@ -36,222 +39,85 @@ Interactor.call(message: 'something')
|
|
36
39
|
#=> #<IIInteractor::Context message="something", result="called by something">
|
37
40
|
```
|
38
41
|
|
39
|
-
The first argument of `call` is set to `@context`.
|
40
|
-
The return value of `call` is the same as `@context`.
|
42
|
+
The first argument of `Interactor.call` is set to `@context`.
|
43
|
+
The return value of `Interactor.call` is the same as `@context`.
|
41
44
|
|
42
|
-
|
45
|
+
You can define context variables used in interactor explicitly.
|
46
|
+
`context_in` copies context to instance variables of interactor,
|
47
|
+
while `context_out` copies instance variables of interactor to context.
|
43
48
|
|
44
|
-
|
49
|
+
### Context options
|
45
50
|
|
46
|
-
|
47
|
-
* `around_call`
|
48
|
-
* `after_call`
|
49
|
-
|
50
|
-
For example:
|
51
|
+
You can define required context as follows:
|
51
52
|
|
52
53
|
```ruby
|
53
54
|
class Interactor < IIInteractor::Base
|
54
|
-
|
55
|
-
@message = @context.message
|
56
|
-
end
|
57
|
-
|
58
|
-
def call
|
59
|
-
puts @message
|
60
|
-
end
|
55
|
+
context_in :input, required: true
|
61
56
|
end
|
62
57
|
|
63
|
-
Interactor.call
|
64
|
-
#=>
|
58
|
+
Interactor.call
|
59
|
+
#=> IIInteractor::RequiredContextError (missing required context: input2)
|
65
60
|
```
|
66
61
|
|
67
|
-
|
68
|
-
|
69
|
-
You can call other interactors in the same context using `interact`:
|
62
|
+
You can also define default value as follows:
|
70
63
|
|
71
64
|
```ruby
|
72
|
-
class
|
73
|
-
|
74
|
-
puts self.class.name
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
class BInteractor < IIInteractor::Base
|
79
|
-
def call
|
80
|
-
puts self.class.name
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
class MainInteractor < IIInteractor::Base
|
85
|
-
interact AInteractor
|
86
|
-
interact BInteractor
|
87
|
-
end
|
88
|
-
|
89
|
-
MainInteractor.call
|
90
|
-
#=> AInteractor
|
91
|
-
# BInteractor
|
92
|
-
```
|
93
|
-
|
94
|
-
#### Named interaction
|
95
|
-
|
96
|
-
You can also define named interactions.
|
97
|
-
The interactors to be called are looked up from all interactors.
|
98
|
-
|
99
|
-
```ruby
|
100
|
-
class AInteractor < IIInteractor::Base
|
101
|
-
react :some_name
|
102
|
-
|
103
|
-
def call
|
104
|
-
puts self.class.name
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
|
-
class BInteractor < IIInteractor::Base
|
109
|
-
react :some_name
|
110
|
-
|
111
|
-
def call
|
112
|
-
puts self.class.name
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
|
-
class MainInteractor < IIInteractor::Base
|
117
|
-
interact :some_name
|
118
|
-
end
|
119
|
-
|
120
|
-
MainInteractor.call
|
121
|
-
#=> AInteractor
|
122
|
-
# BInteractor
|
123
|
-
```
|
124
|
-
|
125
|
-
Note followings:
|
126
|
-
|
127
|
-
* All files in `app/interactors` are loaded in development mode to lookup interactors having same name.
|
128
|
-
* The called interactors are unordered.
|
129
|
-
|
130
|
-
#### Object based interaction
|
131
|
-
|
132
|
-
You can also define object based interactions.
|
133
|
-
The interactors to be called are looked up from the namespace corresponding with caller interactor.
|
134
|
-
|
135
|
-
```ruby
|
136
|
-
class A
|
137
|
-
end
|
138
|
-
|
139
|
-
class B
|
140
|
-
end
|
141
|
-
|
142
|
-
class Main::AInteractor < IIInteractor::Base
|
143
|
-
def call
|
144
|
-
puts self.class.name
|
145
|
-
end
|
146
|
-
end
|
65
|
+
class Interactor < IIInteractor::Base
|
66
|
+
context_in :input, default: 'input'
|
147
67
|
|
148
|
-
class Main::BInteractor < IIInteractor::Base
|
149
68
|
def call
|
150
|
-
puts
|
69
|
+
puts @input
|
151
70
|
end
|
152
71
|
end
|
153
72
|
|
154
|
-
|
155
|
-
|
156
|
-
interact B
|
157
|
-
end
|
158
|
-
|
159
|
-
MainInteractor.call
|
160
|
-
#=> Main::AInteractor
|
161
|
-
# Main::BInteractor
|
73
|
+
Interactor.call
|
74
|
+
#=> input
|
162
75
|
```
|
163
76
|
|
164
|
-
|
165
|
-
|
166
|
-
You can also customize lookup of interactors as follows:
|
77
|
+
You can also set context from return value of `call` method:
|
167
78
|
|
168
79
|
```ruby
|
169
|
-
class
|
170
|
-
|
171
|
-
puts self.class.name
|
172
|
-
end
|
173
|
-
end
|
80
|
+
class Interactor < IIInteractor::Base
|
81
|
+
context_out :result, from_return: true
|
174
82
|
|
175
|
-
class BInteractor < IIInteractor::Base
|
176
83
|
def call
|
177
|
-
|
178
|
-
end
|
179
|
-
end
|
180
|
-
|
181
|
-
class MainInteractor < IIInteractor::Base
|
182
|
-
# set block
|
183
|
-
interact do
|
184
|
-
if @context.condition == 'A'
|
185
|
-
AInteractor
|
186
|
-
else
|
187
|
-
BInteractor
|
188
|
-
end
|
189
|
-
end
|
190
|
-
|
191
|
-
# set method name
|
192
|
-
interact :conditional_interactors
|
193
|
-
|
194
|
-
def conditional_interactors
|
195
|
-
if @context.condition == 'A'
|
196
|
-
AInteractor
|
197
|
-
else
|
198
|
-
BInteractor
|
199
|
-
end
|
84
|
+
'returned value'
|
200
85
|
end
|
201
86
|
end
|
202
87
|
|
203
|
-
|
204
|
-
#=>
|
205
|
-
|
206
|
-
MainInteractor.call(condition: 'B')
|
207
|
-
#=> BInteractor
|
88
|
+
Interactor.call.result
|
89
|
+
#=> returned value
|
208
90
|
```
|
209
91
|
|
210
|
-
|
92
|
+
### Coactions
|
211
93
|
|
212
|
-
You can
|
94
|
+
You can call other interactors in the same context using `coact`:
|
213
95
|
|
214
96
|
```ruby
|
215
|
-
class NestedAInteractor < IIInteractor::Base
|
216
|
-
def call
|
217
|
-
puts self.class.name
|
218
|
-
end
|
219
|
-
end
|
220
|
-
|
221
|
-
class NestedBInteractor < IIInteractor::Base
|
222
|
-
def call
|
223
|
-
puts self.class.name
|
224
|
-
end
|
225
|
-
end
|
226
|
-
|
227
97
|
class AInteractor < IIInteractor::Base
|
228
|
-
interact NestedAInteractor
|
229
|
-
|
230
98
|
def call
|
231
99
|
puts self.class.name
|
232
100
|
end
|
233
101
|
end
|
234
102
|
|
235
103
|
class BInteractor < IIInteractor::Base
|
236
|
-
interact NestedBInteractor
|
237
|
-
|
238
104
|
def call
|
239
105
|
puts self.class.name
|
240
106
|
end
|
241
107
|
end
|
242
108
|
|
243
109
|
class MainInteractor < IIInteractor::Base
|
244
|
-
|
245
|
-
|
110
|
+
coact AInteractor
|
111
|
+
coact BInteractor
|
246
112
|
end
|
247
113
|
|
248
114
|
MainInteractor.call
|
249
|
-
#=>
|
250
|
-
# AInteractor
|
251
|
-
# NestedBInteractor
|
115
|
+
#=> AInteractor
|
252
116
|
# BInteractor
|
253
117
|
```
|
254
118
|
|
119
|
+
See [coactive](https://github.com/kanety/coactive) for more `coact` examples:
|
120
|
+
|
255
121
|
### Stop interactions
|
256
122
|
|
257
123
|
You can stop interactions as follows:
|
@@ -271,8 +137,8 @@ class BInteractor < IIInteractor::Base
|
|
271
137
|
end
|
272
138
|
|
273
139
|
class MainInteractor < IIInteractor::Base
|
274
|
-
|
275
|
-
|
140
|
+
coact AInteractor
|
141
|
+
coact BInteractor
|
276
142
|
end
|
277
143
|
|
278
144
|
context = MainInteractor.call
|
@@ -314,8 +180,8 @@ class BInteractor < IIInteractor::Base
|
|
314
180
|
end
|
315
181
|
|
316
182
|
class MainInteractor < IIInteractor::Base
|
317
|
-
|
318
|
-
|
183
|
+
coact AInteractor
|
184
|
+
coact BInteractor
|
319
185
|
end
|
320
186
|
|
321
187
|
context = MainInteractor.call
|
@@ -329,6 +195,38 @@ context.failure?
|
|
329
195
|
#=> true
|
330
196
|
```
|
331
197
|
|
198
|
+
### Callbacks
|
199
|
+
|
200
|
+
Following callbacks are available:
|
201
|
+
|
202
|
+
* `before_all`, `around_all`, `after_all`
|
203
|
+
* `before_call`, `around_call`, `after_call`
|
204
|
+
|
205
|
+
`*_all` wraps all coactors, and `*_call` wraps `call` method.
|
206
|
+
That is, `before_all` is called before running all coactors, and `before_call` is called before running `call` method.
|
207
|
+
For example:
|
208
|
+
|
209
|
+
```ruby
|
210
|
+
class Interactor < IIInteractor::Base
|
211
|
+
before_all do
|
212
|
+
puts "before_all"
|
213
|
+
end
|
214
|
+
|
215
|
+
before_call do
|
216
|
+
puts "before_call"
|
217
|
+
end
|
218
|
+
|
219
|
+
def call
|
220
|
+
puts @context.message
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
Interactor.call(message: 'something')
|
225
|
+
#=> before_all
|
226
|
+
# before_call
|
227
|
+
# something
|
228
|
+
```
|
229
|
+
|
332
230
|
### Pass a block
|
333
231
|
|
334
232
|
You can pass a block to `call` method of a interactor.
|
@@ -348,8 +246,8 @@ class BInteractor < IIInteractor::Base
|
|
348
246
|
end
|
349
247
|
|
350
248
|
class MainInteractor < IIInteractor::Base
|
351
|
-
|
352
|
-
|
249
|
+
coact AInteractor
|
250
|
+
coact BInteractor
|
353
251
|
end
|
354
252
|
|
355
253
|
MainInteractor.call do |interactor, message|
|
@@ -371,7 +269,9 @@ IIInteractor::LogSubscriber.attach_to :ii_interactor
|
|
371
269
|
This subscriber will write logs in debug mode as the following example:
|
372
270
|
|
373
271
|
```
|
374
|
-
|
272
|
+
Calling BasicInteractor with #<IIInteractor::Context ...>
|
273
|
+
...
|
274
|
+
Called BasicInteractor (Duration: 0.1ms, Allocations: 4)
|
375
275
|
```
|
376
276
|
|
377
277
|
## Contributing
|
data/ii_interactor.gemspec
CHANGED
data/lib/ii_interactor/base.rb
CHANGED
@@ -1,18 +1,18 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative 'context'
|
4
3
|
require_relative 'core'
|
5
4
|
require_relative 'callbacks'
|
6
5
|
require_relative 'instrumentation'
|
7
|
-
require_relative '
|
8
|
-
require_relative '
|
6
|
+
require_relative 'context'
|
7
|
+
require_relative 'contextualizer'
|
8
|
+
require_relative 'coactors'
|
9
9
|
|
10
10
|
module IIInteractor
|
11
11
|
class Base
|
12
12
|
include Core
|
13
13
|
include Callbacks
|
14
14
|
include Instrumentation
|
15
|
-
include
|
16
|
-
include
|
15
|
+
include Contextualizer
|
16
|
+
include Coactors
|
17
17
|
end
|
18
18
|
end
|
@@ -6,9 +6,16 @@ module IIInteractor
|
|
6
6
|
include ActiveSupport::Callbacks
|
7
7
|
|
8
8
|
included do
|
9
|
+
define_callbacks :all
|
9
10
|
define_callbacks :call
|
10
11
|
end
|
11
12
|
|
13
|
+
def call_all
|
14
|
+
run_callbacks :all do
|
15
|
+
super
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
12
19
|
def call_self
|
13
20
|
run_callbacks :call do
|
14
21
|
super
|
@@ -16,6 +23,18 @@ module IIInteractor
|
|
16
23
|
end
|
17
24
|
|
18
25
|
class_methods do
|
26
|
+
def before_all(*args, &block)
|
27
|
+
set_callback(:all, :before, *args, &block)
|
28
|
+
end
|
29
|
+
|
30
|
+
def after_all(*args, &block)
|
31
|
+
set_callback(:all, :after, *args, &block)
|
32
|
+
end
|
33
|
+
|
34
|
+
def around_all(*args, &block)
|
35
|
+
set_callback(:all, :around, *args, &block)
|
36
|
+
end
|
37
|
+
|
19
38
|
def before_call(*args, &block)
|
20
39
|
set_callback(:call, :before, *args, &block)
|
21
40
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module IIInteractor
|
4
|
+
module Coactors
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
include Coactive::Base
|
9
|
+
|
10
|
+
configure_coactive do |config|
|
11
|
+
config.load_paths = ['app/interactors']
|
12
|
+
config.class_suffix = 'Interactor'
|
13
|
+
config.use_cache = true
|
14
|
+
config.lookup_superclass_until = ['ActiveRecord::Base', 'ActiveModel::Base']
|
15
|
+
end
|
16
|
+
|
17
|
+
class << self
|
18
|
+
alias_method :interact, :coact
|
19
|
+
alias_method :react, :coaction
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/lib/ii_interactor/config.rb
CHANGED
@@ -1,14 +1,22 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module IIInteractor
|
4
|
-
class Context <
|
5
|
-
def initialize(
|
4
|
+
class Context < Coactive::Context
|
5
|
+
def initialize(data = {}, &block)
|
6
6
|
super
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
7
|
+
@_data[:_block] ||= block
|
8
|
+
@_data[:_failed] ||= false
|
9
|
+
@_data[:_stopped] ||= false
|
10
|
+
@_data[:_called] ||= []
|
11
|
+
end
|
12
|
+
|
13
|
+
def to_s
|
14
|
+
attrs = @_data.reject { |k, _| k.to_s =~ /^_/ }.map { |k, v| "#{k}=#{v.to_s.truncate(300)}" }.join(', ')
|
15
|
+
"#<#{self.class} #{attrs}>"
|
16
|
+
end
|
17
|
+
|
18
|
+
def call_block!(*args)
|
19
|
+
@_data[:_block].call(*args) if @_data[:_block]
|
12
20
|
end
|
13
21
|
|
14
22
|
def success?
|
@@ -16,21 +24,27 @@ module IIInteractor
|
|
16
24
|
end
|
17
25
|
|
18
26
|
def failure?
|
19
|
-
|
27
|
+
@_data[:_failed] == true
|
20
28
|
end
|
21
29
|
|
22
30
|
def stopped?
|
23
|
-
|
31
|
+
@_data[:_stopped] == true
|
24
32
|
end
|
25
33
|
|
26
34
|
def fail!(data = {})
|
27
|
-
|
28
|
-
data.each { |k, v|
|
35
|
+
@_data[:_failed] = true
|
36
|
+
data.each { |k, v| @_data[k] = v }
|
37
|
+
define_accessors!(data.keys)
|
29
38
|
end
|
30
39
|
|
31
40
|
def stop!(data = {})
|
32
|
-
|
33
|
-
data.each { |k, v|
|
41
|
+
@_data[:_stopped] = true
|
42
|
+
data.each { |k, v| @_data[k] = v }
|
43
|
+
define_accessors!(data.keys)
|
44
|
+
end
|
45
|
+
|
46
|
+
def called!(interactor)
|
47
|
+
@_data[:_called] << interactor
|
34
48
|
end
|
35
49
|
end
|
36
50
|
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module IIInteractor
|
4
|
+
module Contextualizer
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
include Coactive::Contextualizer
|
7
|
+
|
8
|
+
def call_self
|
9
|
+
contextualize do
|
10
|
+
super
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class_methods do
|
15
|
+
def context_in(*names, **options)
|
16
|
+
context(*names, **options)
|
17
|
+
end
|
18
|
+
|
19
|
+
def context_out(*names, **options)
|
20
|
+
options[:output] = true
|
21
|
+
if options.delete(:from_return)
|
22
|
+
options[:output] = :return
|
23
|
+
end
|
24
|
+
context(*names, **options)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/lib/ii_interactor/core.rb
CHANGED
@@ -3,35 +3,41 @@
|
|
3
3
|
module IIInteractor
|
4
4
|
module Core
|
5
5
|
extend ActiveSupport::Concern
|
6
|
+
include Coactive::Initializer
|
6
7
|
|
7
8
|
included do
|
8
|
-
|
9
|
+
self.context_class = IIInteractor::Context
|
9
10
|
end
|
10
11
|
|
11
|
-
def initialize(
|
12
|
-
|
13
|
-
context
|
14
|
-
else
|
15
|
-
IIInteractor::Context.new(context, &block)
|
16
|
-
end
|
12
|
+
def initialize(*)
|
13
|
+
super
|
17
14
|
end
|
18
15
|
|
19
16
|
def call_all
|
20
|
-
planned =
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
17
|
+
planned = case IIInteractor.config.traversal
|
18
|
+
when :preorder
|
19
|
+
[self] + coactors
|
20
|
+
when :postorder
|
21
|
+
coactors + [self]
|
22
|
+
when :inorder
|
23
|
+
planned = coactors.in_groups(2, false)
|
24
|
+
planned[0] + [self] + planned[1]
|
25
|
+
end
|
26
|
+
|
27
|
+
planned.each do |interactor|
|
28
|
+
if interactor == self
|
29
|
+
call_self
|
25
30
|
else
|
26
|
-
interactor.call_all
|
31
|
+
interactor.new(@context).call_all
|
27
32
|
end
|
28
33
|
break if @context.stopped?
|
29
34
|
end
|
30
35
|
end
|
31
36
|
|
32
37
|
def call_self
|
33
|
-
call
|
34
|
-
|
38
|
+
call.tap do
|
39
|
+
@context.called!(self)
|
40
|
+
end
|
35
41
|
end
|
36
42
|
|
37
43
|
def call
|
@@ -41,7 +47,7 @@ module IIInteractor
|
|
41
47
|
end
|
42
48
|
|
43
49
|
def inform(*args)
|
44
|
-
@context.
|
50
|
+
@context.call_block!(*([self] + args))
|
45
51
|
end
|
46
52
|
|
47
53
|
def fail!(data = {})
|
@@ -54,12 +60,12 @@ module IIInteractor
|
|
54
60
|
end
|
55
61
|
|
56
62
|
class_methods do
|
57
|
-
def call(
|
58
|
-
interactor = new(
|
63
|
+
def call(args = {}, &block)
|
64
|
+
interactor = new(args, &block)
|
59
65
|
interactor.call_all
|
60
66
|
interactor.context
|
61
67
|
rescue UnprogressableError
|
62
|
-
interactor.context
|
68
|
+
interactor.context[:_called].reverse.each do |called|
|
63
69
|
called.rollback
|
64
70
|
end
|
65
71
|
interactor.context
|
data/lib/ii_interactor/errors.rb
CHANGED
@@ -4,6 +4,11 @@ module IIInteractor
|
|
4
4
|
module Instrumentation
|
5
5
|
extend ActiveSupport::Concern
|
6
6
|
|
7
|
+
def call_all
|
8
|
+
ActiveSupport::Notifications.instrument 'calling.ii_interactor', interactor: self
|
9
|
+
super
|
10
|
+
end
|
11
|
+
|
7
12
|
def call_self
|
8
13
|
ActiveSupport::Notifications.instrument 'call.ii_interactor', interactor: self do
|
9
14
|
super
|
@@ -2,6 +2,13 @@
|
|
2
2
|
|
3
3
|
module IIInteractor
|
4
4
|
class LogSubscriber < ActiveSupport::LogSubscriber
|
5
|
+
def calling(event)
|
6
|
+
debug do
|
7
|
+
interactor = event.payload[:interactor]
|
8
|
+
"Calling #{interactor.class} with #{interactor.context}"
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
5
12
|
def call(event)
|
6
13
|
debug do
|
7
14
|
interactor = event.payload[:interactor]
|
@@ -9,6 +16,8 @@ module IIInteractor
|
|
9
16
|
end
|
10
17
|
end
|
11
18
|
|
19
|
+
private
|
20
|
+
|
12
21
|
def additional_log(event)
|
13
22
|
additions = ["Duration: %.1fms" % event.duration]
|
14
23
|
additions << "Allocations: %d" % event.allocations if event.respond_to?(:allocations)
|
data/lib/ii_interactor.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
require 'active_support'
|
2
|
+
require 'coactive'
|
2
3
|
|
3
4
|
require 'ii_interactor/version'
|
4
5
|
require 'ii_interactor/errors'
|
5
6
|
require 'ii_interactor/config'
|
6
7
|
require 'ii_interactor/base'
|
7
|
-
require 'ii_interactor/loader'
|
8
8
|
require 'ii_interactor/log_subscriber'
|
9
9
|
|
10
10
|
module IIInteractor
|
@@ -16,9 +16,5 @@ module IIInteractor
|
|
16
16
|
def config
|
17
17
|
Config
|
18
18
|
end
|
19
|
-
|
20
|
-
def load
|
21
|
-
Loader.call
|
22
|
-
end
|
23
19
|
end
|
24
20
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ii_interactor
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yoshikazu Kaneta
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-01-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -24,6 +24,20 @@ dependencies:
|
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '5.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: coactive
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0.2'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0.2'
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: rails
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -116,22 +130,19 @@ files:
|
|
116
130
|
- gemfiles/rails52.gemfile
|
117
131
|
- gemfiles/rails60.gemfile
|
118
132
|
- gemfiles/rails61.gemfile
|
133
|
+
- gemfiles/rails70.gemfile
|
119
134
|
- ii_interactor.gemspec
|
120
135
|
- lib/ii_interactor.rb
|
121
136
|
- lib/ii_interactor/base.rb
|
122
137
|
- lib/ii_interactor/callbacks.rb
|
138
|
+
- lib/ii_interactor/coactors.rb
|
123
139
|
- lib/ii_interactor/config.rb
|
124
140
|
- lib/ii_interactor/context.rb
|
141
|
+
- lib/ii_interactor/contextualizer.rb
|
125
142
|
- lib/ii_interactor/core.rb
|
126
143
|
- lib/ii_interactor/errors.rb
|
127
144
|
- lib/ii_interactor/instrumentation.rb
|
128
|
-
- lib/ii_interactor/interaction.rb
|
129
|
-
- lib/ii_interactor/loader.rb
|
130
145
|
- lib/ii_interactor/log_subscriber.rb
|
131
|
-
- lib/ii_interactor/lookup.rb
|
132
|
-
- lib/ii_interactor/lookups/base.rb
|
133
|
-
- lib/ii_interactor/lookups/name.rb
|
134
|
-
- lib/ii_interactor/lookups/object.rb
|
135
146
|
- lib/ii_interactor/version.rb
|
136
147
|
homepage: https://github.com/kanety/ii_interactor
|
137
148
|
licenses: []
|
@@ -151,7 +162,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
151
162
|
- !ruby/object:Gem::Version
|
152
163
|
version: '0'
|
153
164
|
requirements: []
|
154
|
-
rubygems_version: 3.1.
|
165
|
+
rubygems_version: 3.1.6
|
155
166
|
signing_key:
|
156
167
|
specification_version: 4
|
157
168
|
summary: A base interactor to support management of bussiness logic
|
@@ -1,43 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module IIInteractor
|
4
|
-
module Interaction
|
5
|
-
extend ActiveSupport::Concern
|
6
|
-
|
7
|
-
included do
|
8
|
-
class_attribute :_interactions
|
9
|
-
self._interactions = []
|
10
|
-
class_attribute :_reactions
|
11
|
-
self._reactions = []
|
12
|
-
end
|
13
|
-
|
14
|
-
class_methods do
|
15
|
-
def interact(*interactors, **options, &block)
|
16
|
-
if block
|
17
|
-
self._interactions = _interactions + [block]
|
18
|
-
elsif options[:before]
|
19
|
-
index = self._interactions.index { |interaction| interaction == options[:before] }
|
20
|
-
self._interactions = self._interactions.insert(index, *interactors)
|
21
|
-
else
|
22
|
-
self._interactions = _interactions + interactors
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
def interactions
|
27
|
-
self._interactions
|
28
|
-
end
|
29
|
-
|
30
|
-
def clear_interactions
|
31
|
-
self._interactions = []
|
32
|
-
end
|
33
|
-
|
34
|
-
def react(*reactions)
|
35
|
-
self._reactions = _reactions + reactions
|
36
|
-
end
|
37
|
-
|
38
|
-
def reactions
|
39
|
-
self._reactions
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
data/lib/ii_interactor/loader.rb
DELETED
@@ -1,19 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module IIInteractor
|
4
|
-
module Loader
|
5
|
-
class << self
|
6
|
-
def call
|
7
|
-
return unless defined?(Rails)
|
8
|
-
return if Rails.env.production?
|
9
|
-
|
10
|
-
engines = [Rails] + Rails::Engine.subclasses.map(&:instance)
|
11
|
-
engines.each do |engine|
|
12
|
-
Dir["#{engine.root}/app/interactors/**/*.rb"].each do |file|
|
13
|
-
require file
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
data/lib/ii_interactor/lookup.rb
DELETED
@@ -1,66 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative 'lookups/base'
|
4
|
-
require_relative 'lookups/name'
|
5
|
-
require_relative 'lookups/object'
|
6
|
-
|
7
|
-
module IIInteractor
|
8
|
-
module Lookup
|
9
|
-
extend ActiveSupport::Concern
|
10
|
-
|
11
|
-
def lookup_all
|
12
|
-
lookup.map { |interactor| [interactor] + interactor.new(@context).lookup_all }.flatten
|
13
|
-
end
|
14
|
-
|
15
|
-
def lookup
|
16
|
-
self.class._interactions.map do |interaction|
|
17
|
-
if interaction.is_a?(Symbol) && respond_to?(interaction, true)
|
18
|
-
send(interaction)
|
19
|
-
elsif interaction.is_a?(Proc)
|
20
|
-
instance_exec(&interaction)
|
21
|
-
else
|
22
|
-
interaction
|
23
|
-
end
|
24
|
-
end.flatten.compact.map do |interaction|
|
25
|
-
if interaction.is_a?(Class) && interaction < IIInteractor::Base
|
26
|
-
interaction
|
27
|
-
else
|
28
|
-
self.class.lookup(interaction)
|
29
|
-
end
|
30
|
-
end.flatten.compact
|
31
|
-
end
|
32
|
-
|
33
|
-
class_methods do
|
34
|
-
def lookup(*interactions)
|
35
|
-
interactions = _interactions unless interactions
|
36
|
-
interactions.map { |interaction| Lookup.call(self, interaction) }.flatten
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
class << self
|
41
|
-
class_attribute :lookups
|
42
|
-
self.lookups = [Lookups::Name, Lookups::Object]
|
43
|
-
|
44
|
-
class_attribute :cache
|
45
|
-
self.cache = {}
|
46
|
-
|
47
|
-
def call(klass, interaction)
|
48
|
-
with_cache(klass, interaction) do
|
49
|
-
lookup = lookups.detect { |lookup| lookup.call?(interaction) }
|
50
|
-
lookup.new(klass, interaction).call if lookup
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
private
|
55
|
-
|
56
|
-
def with_cache(klass, interaction)
|
57
|
-
if Config.lookup_cache
|
58
|
-
self.cache[klass] ||= {}
|
59
|
-
self.cache[klass][interaction] ||= yield
|
60
|
-
else
|
61
|
-
yield
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
@@ -1,20 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module IIInteractor
|
4
|
-
module Lookups
|
5
|
-
class Base
|
6
|
-
def initialize(klass, interaction)
|
7
|
-
@klass = klass
|
8
|
-
@interaction = interaction
|
9
|
-
end
|
10
|
-
|
11
|
-
def call
|
12
|
-
end
|
13
|
-
|
14
|
-
class << self
|
15
|
-
def call?(interaction)
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
@@ -1,20 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module IIInteractor
|
4
|
-
module Lookups
|
5
|
-
class Name < Base
|
6
|
-
def call
|
7
|
-
IIInteractor.load
|
8
|
-
IIInteractor::Base.descendants.select do |interactor|
|
9
|
-
interactor._reactions.any? { |reaction| reaction == @interaction }
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
class << self
|
14
|
-
def call?(interaction)
|
15
|
-
interaction.is_a?(Symbol)
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
@@ -1,40 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module IIInteractor
|
4
|
-
module Lookups
|
5
|
-
class Object < Base
|
6
|
-
def call
|
7
|
-
return if terminate?
|
8
|
-
|
9
|
-
if @interaction.name.present? && (interactor = resolve)
|
10
|
-
interactor
|
11
|
-
elsif @interaction.superclass
|
12
|
-
self.class.new(@klass, @interaction.superclass).call
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
private
|
17
|
-
|
18
|
-
def terminate?
|
19
|
-
@interaction.name.to_s.in?(['Object', 'ActiveRecord::Base', 'ActiveModel::Base'])
|
20
|
-
end
|
21
|
-
|
22
|
-
def resolve
|
23
|
-
name = resolve_name
|
24
|
-
interactor = name.safe_constantize
|
25
|
-
return interactor if interactor && name == interactor.name
|
26
|
-
end
|
27
|
-
|
28
|
-
def resolve_name
|
29
|
-
namespace = @klass.name.to_s.sub(/Interactor$/, '').to_s
|
30
|
-
[namespace, "#{@interaction.name}Interactor"].join('::')
|
31
|
-
end
|
32
|
-
|
33
|
-
class << self
|
34
|
-
def call?(interaction)
|
35
|
-
interaction.is_a?(Module)
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|