ii_interactor 1.1.0 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
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