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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3d08217ca0d49ae98a2c034ed00bb785aca82359dd90a2d06285a6b6e850b5ac
4
- data.tar.gz: 85d61cde0ae2f9e828637fcf5cd7144aabf9ba42d9842c582f9a86d06e7328d2
3
+ metadata.gz: f27fe194dd295f5882f0533132588686a9fead26c638f86db95b8b66979553bf
4
+ data.tar.gz: '08c3c2fbd0687fb42077215abb8edd0e85a76eda538c418fa5f869f50957ed90'
5
5
  SHA512:
6
- metadata.gz: 148a1e202624098aef8cbe7fcbededf1cd86a03d33c070768e1d75f0aa848363b45e4a9b349e6b614e1f753710d8256a4ac3aed9a39d2bf91a7444a9eb0140fd
7
- data.tar.gz: daf5475ab67cae1eb42043c5b0cc20334683f94e4fdf908e222bcb67e323f81606b8b888a5e14c07b3d31c4a7ee1f68c285fa692f784fe575098f51ed6f20c89
6
+ metadata.gz: ab6289235d21d6085ce7b20d123efd152d1e387f6d17a708a107e735f259036bb87be8533e9e7e5b07613cc9ca14fd0b699521bbb1c6f42c855054884f0e690e
7
+ data.tar.gz: 76c6d853fc4ef5b6103d9dda4cdac6ecb9179b0b21c6b35e72519dd2059bb1efb95a431ae23dca207f51a78e8a8e598c56028851842b98b6a4181221da725f76
@@ -4,21 +4,29 @@ on: [push, pull_request]
4
4
 
5
5
  jobs:
6
6
  test:
7
- runs-on: ubuntu-18.04
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
@@ -2,6 +2,7 @@
2
2
  .project
3
3
  Gemfile.lock
4
4
  coverage/
5
+ gemfiles/*.lock
5
6
  pkg/
6
7
  tmp/
7
8
  spec/dummy/db/*.sqlite3
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
- ### Callbacks
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
- Following callbacks are available:
49
+ ### Context options
45
50
 
46
- * `before_call`
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
- before_call do
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(message: 'something')
64
- #=> something
58
+ Interactor.call
59
+ #=> IIInteractor::RequiredContextError (missing required context: input2)
65
60
  ```
66
61
 
67
- ### Interactions
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 AInteractor < IIInteractor::Base
73
- def call
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 self.class.name
69
+ puts @input
151
70
  end
152
71
  end
153
72
 
154
- class MainInteractor < IIInteractor::Base
155
- interact A
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
- #### Custom interaction
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 AInteractor < IIInteractor::Base
170
- def call
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
- puts self.class.name
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
- MainInteractor.call(condition: 'A')
204
- #=> AInteractor
205
-
206
- MainInteractor.call(condition: 'B')
207
- #=> BInteractor
88
+ Interactor.call.result
89
+ #=> returned value
208
90
  ```
209
91
 
210
- #### Nested interaction
92
+ ### Coactions
211
93
 
212
- You can define nested interactions as follows:
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
- interact AInteractor
245
- interact BInteractor
110
+ coact AInteractor
111
+ coact BInteractor
246
112
  end
247
113
 
248
114
  MainInteractor.call
249
- #=> NestedAInteractor
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
- interact AInteractor
275
- interact BInteractor
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
- interact AInteractor
318
- interact BInteractor
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
- interact AInteractor
352
- interact BInteractor
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
- Called SimpleInteractor (Duration: 0.3ms, Allocations: 42)
272
+ Calling BasicInteractor with #<IIInteractor::Context ...>
273
+ ...
274
+ Called BasicInteractor (Duration: 0.1ms, Allocations: 4)
375
275
  ```
376
276
 
377
277
  ## Contributing
@@ -0,0 +1,5 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem "rails", "~> 7.0.0"
4
+
5
+ gemspec path: "../"
@@ -18,6 +18,7 @@ Gem::Specification.new do |spec|
18
18
  spec.require_paths = ["lib"]
19
19
 
20
20
  spec.add_dependency "activesupport", ">= 5.0"
21
+ spec.add_dependency "coactive", ">= 0.2"
21
22
 
22
23
  spec.add_development_dependency "rails", ">= 5.0"
23
24
  spec.add_development_dependency "sqlite3"
@@ -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 'interaction'
8
- require_relative 'lookup'
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 Interaction
16
- include Lookup
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
@@ -5,6 +5,7 @@ module IIInteractor
5
5
  class_attribute :data
6
6
 
7
7
  self.data = {
8
+ traversal: :postorder,
8
9
  lookup_cache: true
9
10
  }
10
11
 
@@ -1,14 +1,22 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module IIInteractor
4
- class Context < OpenStruct
5
- def initialize(hash, &block)
4
+ class Context < Coactive::Context
5
+ def initialize(data = {}, &block)
6
6
  super
7
- self[:_block] = block
8
- self[:_failed] = false
9
- self[:_stopped] = false
10
- self[:_planned] = []
11
- self[:_called] = []
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
- self[:_failed] == true
27
+ @_data[:_failed] == true
20
28
  end
21
29
 
22
30
  def stopped?
23
- self[:_stopped] == true
31
+ @_data[:_stopped] == true
24
32
  end
25
33
 
26
34
  def fail!(data = {})
27
- self[:_failed] = true
28
- data.each { |k, v| self[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
- self[:_stopped] = true
33
- data.each { |k, v| self[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
@@ -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
- attr_reader :context
9
+ self.context_class = IIInteractor::Context
9
10
  end
10
11
 
11
- def initialize(context = {}, &block)
12
- @context = if context.is_a?(IIInteractor::Context)
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 = lookup.map { |interactor| interactor.new(@context) } + [self]
21
- @context._planned += planned
22
- planned.each_with_index do |interactor, i|
23
- if i == planned.size - 1
24
- interactor.call_self
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
- @context._called << self
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._block.call(*([self] + args)) if @context._block
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(context = {}, &block)
58
- interactor = new(context, &block)
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._called.reverse.each do |called|
68
+ interactor.context[:_called].reverse.each do |called|
63
69
  called.rollback
64
70
  end
65
71
  interactor.context
@@ -3,4 +3,7 @@
3
3
  module IIInteractor
4
4
  class UnprogressableError < StandardError
5
5
  end
6
+
7
+ class RequiredContextError < StandardError
8
+ end
6
9
  end
@@ -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)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module IIInteractor
4
- VERSION = '1.1.0'
4
+ VERSION = '2.1.0'
5
5
  end
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: 1.1.0
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: 2021-07-19 00:00:00.000000000 Z
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.2
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
@@ -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
@@ -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