interactify 0.2.0.pre.alpha.1 → 0.3.0.pre.alpha.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -2
- data/README.md +44 -87
- data/lib/interactify/contract_helpers.rb +2 -2
- data/lib/interactify/dsl.rb +2 -0
- data/lib/interactify/each_chain.rb +10 -4
- data/lib/interactify/if_interactor.rb +8 -4
- data/lib/interactify/interactor_wrapper.rb +72 -0
- data/lib/interactify/{organizer_call_monkey_patch.rb → organizer.rb} +4 -19
- data/lib/interactify/unique_klass_name.rb +21 -0
- data/lib/interactify/version.rb +1 -1
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 918f4f6ae335bb5b8a748603af6a2e9d91dc11ad3d887803bbb2c7b2ba41730e
|
4
|
+
data.tar.gz: fe6506fe246a82d48f5a614d5c576cf74e49f38953c1d4ae98d52f1649f03aaf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ce377154a79b527f6eaebe3258d76aadd327521abbe86847b8c9d87b5710e1782bdb02b20b3ef3661ac6dc4ee1d0c6843fdd819ccf6dda8f701e9d95063d5a9c
|
7
|
+
data.tar.gz: 553271645575873bc2a95968c2ff7f01a556dd24527974b6a7bb958a8eeb9f8bb66504bdace2c3736e6faac82c1a438f07d27afa85c3fdc8ac5b051cac4e20c5
|
data/CHANGELOG.md
CHANGED
@@ -1,9 +1,13 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
-
## [0.1.0] - 2023-12-16
|
3
|
+
## [0.1.0-alpha.1] - 2023-12-16
|
4
4
|
|
5
5
|
- Initial release
|
6
6
|
|
7
|
-
## [0.2.0] - 2023-12-27
|
7
|
+
## [0.2.0-alpha.1] - 2023-12-27
|
8
8
|
|
9
9
|
- Added support for Interactify.promising syntax in organizers
|
10
|
+
|
11
|
+
## [0.3.0-alpha.1] - 2023-12-29
|
12
|
+
|
13
|
+
- Added support for `{if: :condition, then: A, else: B}` in organizers
|
data/README.md
CHANGED
@@ -1,18 +1,9 @@
|
|
1
1
|
# Interactify
|
2
2
|
|
3
|
-
[
|
4
|
-
However, sometimes in complex interactor chains, the complex debugging happens at one level up from your easy to read and test interactors.
|
5
|
-
|
6
|
-
[interactor-contracts](https://github.com/michaelherold/interactor-contracts) does a fantastic job of making your interactor chains more reliable.
|
7
|
-
|
8
|
-
Interactify wraps the interactor and interactor-contracts gem and provides additional functionality making chaining and understanding interactor chains easier.
|
9
|
-
|
10
|
-
This is a bells and whistles gem and assumes you are working in a Rails project with Sidekiq.
|
11
|
-
However, I'm open to the idea of making it more focused and making these more pluggable.
|
12
|
-
|
3
|
+
Interactify enhances Rails applications by simplifying complex interactor chains. This gem builds on [interactors](https://github.com/collectiveidea/interactor) and [interactor-contracts](https://github.com/michaelherold/interactor-contracts) to improve readability and maintainability of business logic. It's optimized for Rails projects using Sidekiq, offering advanced features for chain management and debugging. Interactify is about making interactor usage in Rails more efficient and less error-prone, reducing the overhead of traditional interactor orchestration.
|
13
4
|
## Installation
|
14
5
|
|
15
|
-
```
|
6
|
+
```ruby
|
16
7
|
gem 'interactify'
|
17
8
|
```
|
18
9
|
|
@@ -39,10 +30,15 @@ end
|
|
39
30
|
```ruby
|
40
31
|
# e.g. in spec/supoort/interactify.rb
|
41
32
|
require 'interactify/rspec/matchers'
|
33
|
+
|
34
|
+
expect(described_class).to expect_inputs(:foo, :bar, :baz)
|
35
|
+
expect(described_class).to promise_outputs(:fee, :fi, :fo, :fum)
|
42
36
|
```
|
43
37
|
|
44
38
|
### Syntactic Sugar
|
45
39
|
- Everything is an Organizer/Interactor and supports interactor-contracts.
|
40
|
+
- They only becomes considered an organizer once `organize` is called.
|
41
|
+
- They could technically be both (if you want?) but you have to remember to call `super` within `call` to trigger the organized interactors.
|
46
42
|
- Concise syntax for most common scenarios with `expects` and `promises`. Verifying the presence of the keys/values.
|
47
43
|
- Automatic delegation of expected and promised keys to the context.
|
48
44
|
|
@@ -63,7 +59,6 @@ class LoadOrder
|
|
63
59
|
required(:order).filled
|
64
60
|
end
|
65
61
|
|
66
|
-
|
67
62
|
def call
|
68
63
|
context.order = Order.find(context.id)
|
69
64
|
end
|
@@ -89,8 +84,8 @@ end
|
|
89
84
|
|
90
85
|
### Lambdas
|
91
86
|
|
92
|
-
With vanilla interactors, it'
|
93
|
-
So we added support.
|
87
|
+
With vanilla interactors, it wasn't possible to use lambdas in organizers.
|
88
|
+
But sometimes we only want a lambda. So we added support.
|
94
89
|
|
95
90
|
```ruby
|
96
91
|
organize LoadOrder, ->(context) { context.order = context.order.decorate }
|
@@ -157,7 +152,6 @@ class DoSomethingWithOrder
|
|
157
152
|
end
|
158
153
|
```
|
159
154
|
|
160
|
-
|
161
155
|
```ruby
|
162
156
|
# after
|
163
157
|
class OuterOrganizer
|
@@ -178,7 +172,6 @@ class LoadOrder
|
|
178
172
|
end
|
179
173
|
end
|
180
174
|
|
181
|
-
|
182
175
|
class DoSomethingWithOrder
|
183
176
|
# ... boilerplate ...
|
184
177
|
def call
|
@@ -187,7 +180,7 @@ class DoSomethingWithOrder
|
|
187
180
|
end
|
188
181
|
```
|
189
182
|
|
190
|
-
### Conditionals (if/else)
|
183
|
+
### Conditionals (if/else) with lambda
|
191
184
|
|
192
185
|
Along the same lines of each/iteration. We sometimes have to 'break the chain' with interactors just to conditionally call one interactor chain path or another.
|
193
186
|
|
@@ -212,7 +205,6 @@ class InnerThing
|
|
212
205
|
end
|
213
206
|
```
|
214
207
|
|
215
|
-
|
216
208
|
```ruby
|
217
209
|
# after
|
218
210
|
class OuterThing
|
@@ -222,9 +214,16 @@ class OuterThing
|
|
222
214
|
self.if(->(c){ c.thing == 'a' }, DoThingA, DoThingB),
|
223
215
|
end
|
224
216
|
|
217
|
+
# or hash syntax
|
218
|
+
class OuterThing
|
219
|
+
# ... boilerplate ...
|
220
|
+
organize \
|
221
|
+
{if: :key_set_on_context, then: DoThingA, else: DoThingB},
|
222
|
+
AfterBothCases
|
223
|
+
end
|
225
224
|
```
|
226
225
|
|
227
|
-
###
|
226
|
+
### Conditionals with a key from the context
|
228
227
|
|
229
228
|
```ruby
|
230
229
|
class OuterThing
|
@@ -348,19 +347,19 @@ class SomeInteractor
|
|
348
347
|
# ...
|
349
348
|
end
|
350
349
|
end
|
351
|
-
|
352
|
-
clsas SomeInteractorJob
|
353
|
-
include Sidekiq::Job
|
354
|
-
|
355
|
-
def perform(*args)
|
356
|
-
SomeInteractor.call(*args)
|
357
|
-
end
|
358
|
-
end
|
359
350
|
```
|
360
351
|
|
361
352
|
```diff
|
362
|
-
-SomeInteractor.call(*args)
|
363
|
-
+SomeInteractorJob
|
353
|
+
- SomeInteractor.call(*args)
|
354
|
+
+ class SomeInteractorJob
|
355
|
+
+ include Sidekiq::Job
|
356
|
+
+
|
357
|
+
+ def perform(*args)
|
358
|
+
+ SomeInteractor.call(*args)
|
359
|
+
+ end
|
360
|
+
+ end
|
361
|
+
+
|
362
|
+
+ SomeInteractorJob.perform_async(*args)
|
364
363
|
```
|
365
364
|
|
366
365
|
```ruby
|
@@ -377,8 +376,8 @@ end
|
|
377
376
|
No need to manually create a job class or handle the perform/call impedance mismatch
|
378
377
|
|
379
378
|
```diff
|
380
|
-
-SomeInteractor.call!(*args)
|
381
|
-
+SomeInteractor::Async.call!(*args)
|
379
|
+
- SomeInteractor.call!(*args)
|
380
|
+
+ SomeInteractor::Async.call!(*args)
|
382
381
|
```
|
383
382
|
|
384
383
|
This also makes it easy to add cron jobs to run interactors. As any interactor can be asyncified.
|
@@ -386,8 +385,6 @@ By using it's internal Async class.
|
|
386
385
|
|
387
386
|
N.B. as your class is now executing asynchronously you can no longer rely on its promises later on in the chain.
|
388
387
|
|
389
|
-
|
390
|
-
|
391
388
|
## FAQs
|
392
389
|
- This is ugly isn't it?
|
393
390
|
|
@@ -403,73 +400,33 @@ class OuterOrganizer
|
|
403
400
|
)
|
404
401
|
end
|
405
402
|
```
|
403
|
+
1. Do you find the syntax of OuterOrganizer ugly?
|
406
404
|
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
- Is this interactor/interactor-contracts compatible?
|
411
|
-
Yes and we use them as dependencies. It's possible we'd drop those dependencies in the future but unlikely. I think it's highly likely we'd retain compatibility.
|
412
|
-
|
413
|
-
|
414
|
-
- Why not propose changes to the interactor or interactor-contracts gem?
|
415
|
-
Honestly, I think both are great and why we've built on top of them.
|
416
|
-
I presume they'd object to such an extensive opinionated change, and I think that would be the right decision too.
|
417
|
-
If this becomes more stable, less coupled to Rails, there's interest, and things we can provide upstream I'd be happy to propose changes to those gems.
|
418
|
-
|
419
|
-
- Isn't this all just syntactic sugar?
|
420
|
-
Yes, but it's sugar that makes the code easier to read and understand.
|
421
|
-
|
422
|
-
- Is it really easier to parse this new DSL/syntax than POROs?
|
423
|
-
That's subjective, but I think so. The benefit is you have fewer extraneous files patching over a common problem in interactors.
|
405
|
+
While the syntax might seem unconventional initially, its conceptual elegance lies in streamlining complex interactor chains. Traditional methods often involve navigating through multiple files, creating a hidden and cumbersome architecture. This gem aims to alleviate that by centralizing operations, making the overall process more intuitive.
|
424
406
|
|
425
|
-
|
426
|
-
Again this is subjective, but if you've worked with apps with hundred or thousands of interactors, you'll have encountered these problems.
|
427
|
-
I think when we work with interactors we're in one of two modes.
|
428
|
-
Hunting to find the interactor we need to change, or working on the interactor we need to change.
|
429
|
-
This makes the first step much easier.
|
430
|
-
The second step has always been a great experience with interactors.
|
407
|
+
2. Is this compatible with interactor/interactor-contracts?
|
431
408
|
|
432
|
-
|
433
|
-
If you're not heavily invested into interactors this may not be for you.
|
434
|
-
I love the chaining interactors provide.
|
435
|
-
I love the contracts.
|
436
|
-
I love the simplicity of the interface.
|
437
|
-
I love the way they can be composed.
|
438
|
-
I love the way they can be tested.
|
439
|
-
When I've used service objects, I've found them to be more complex to test and compose.
|
440
|
-
I can't see a clean way that using service objects to compose interactors could work well without losing some of the aforementioned benefits.
|
409
|
+
Yes, it's fully compatible. We currently use these as dependencies. While there's a possibility of future changes, maintaining this compatibility is a priority.
|
441
410
|
|
442
|
-
|
443
|
-
We want to add support for explicitly specifying promises in organizers.
|
411
|
+
3. Why not suggest enhancements to the interactor or interactor-contracts gems?
|
444
412
|
|
445
|
-
|
446
|
-
|
447
|
-
This is another variation of the "interactors themselves are great but their coordination and finding where things happen is hard in large applications".
|
448
|
-
|
449
|
-
By adding promise notation to organizers, we can signal to the reader that 'here in this part of the chain is the thing you are looking for'.
|
450
|
-
|
451
|
-
A writer of an organizer may expect LoadOrder to promise :order, but for the reader, it's not quite as explicit.
|
452
|
-
The expected syntax will be
|
453
|
-
|
454
|
-
```ruby
|
455
|
-
organize \
|
456
|
-
LoadOrder.promising(:order),
|
457
|
-
TakePayment.promising(:payment_transaction)
|
458
|
-
```
|
413
|
+
These gems are excellent in their own right, which is why we've built upon them. Proposing such extensive changes might not align with their current philosophy. However, if our approach proves stable and garners interest, we're open to discussing potential contributions to these gems.
|
459
414
|
|
460
|
-
|
415
|
+
4. Is this just syntactic sugar?
|
461
416
|
|
417
|
+
It's more than that. This approach enhances readability and comprehension of the code. It simplifies the structure, making it easier to navigate and maintain.
|
462
418
|
|
463
|
-
|
419
|
+
5. Is the new DSL/syntax easier to understand than plain old Ruby objects (POROs)?
|
464
420
|
|
465
|
-
|
421
|
+
This is subjective, but we believe it is. It reduces the need for numerous files addressing common interactor issues, thereby streamlining the workflow.
|
466
422
|
|
467
|
-
|
423
|
+
6. Doesn't this approach become verbose and complex in large applications?
|
468
424
|
|
469
|
-
|
425
|
+
While it may appear so, this method shines in large-scale applications with numerous interactors. It simplifies locating and modifying the necessary interactors, which is often a cumbersome process.
|
470
426
|
|
471
|
-
|
427
|
+
7. What if I prefer using Service Objects?
|
472
428
|
|
429
|
+
That's completely valid. Service Objects have their merits, but this gem is particularly useful for those deeply engaged with interactors. It capitalizes on the chaining, contracts, simplicity, composability, and testability that interactors offer. Combining Service Objects with interactors might not retain these advantages as effectively.
|
473
430
|
## License
|
474
431
|
|
475
432
|
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
require "interactify/jobable"
|
4
4
|
require "interactify/call_wrapper"
|
5
|
-
require "interactify/
|
5
|
+
require "interactify/organizer"
|
6
6
|
require "interactify/contract_failure"
|
7
7
|
|
8
8
|
module Interactify
|
@@ -48,7 +48,7 @@ module Interactify
|
|
48
48
|
# failure class: Whatever::SomeInteractor::InteractorContractFailure
|
49
49
|
const_set "InteractorContractFailure", c
|
50
50
|
prepend CallWrapper
|
51
|
-
include
|
51
|
+
include Organizer
|
52
52
|
|
53
53
|
on_breach do |breaches|
|
54
54
|
breaches = breaches.map { |b| { b.property => b.messages } }.inject(&:merge)
|
data/lib/interactify/dsl.rb
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require "interactify/each_chain"
|
4
4
|
require "interactify/if_interactor"
|
5
|
+
require "interactify/unique_klass_name"
|
5
6
|
|
6
7
|
module Interactify
|
7
8
|
module Dsl
|
@@ -63,6 +64,7 @@ module Interactify
|
|
63
64
|
|
64
65
|
# attach the class to the calling namespace
|
65
66
|
where_to_attach = self.binding.receiver
|
67
|
+
klass_name = UniqueKlassName.for(where_to_attach, klass_name)
|
66
68
|
where_to_attach.const_set(klass_name, klass)
|
67
69
|
end
|
68
70
|
end
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "interactify/unique_klass_name"
|
4
|
+
|
3
5
|
module Interactify
|
4
6
|
class EachChain
|
5
7
|
attr_reader :each_loop_klasses, :plural_resource_name, :evaluating_receiver
|
@@ -38,7 +40,7 @@ module Interactify
|
|
38
40
|
context[this.singular_resource_name] = resource # context.package = package
|
39
41
|
context[this.singular_resource_index_name] = index # context.package_index = index
|
40
42
|
|
41
|
-
klasses =
|
43
|
+
klasses = InteractorWrapper.wrap_many(self, this.each_loop_klasses)
|
42
44
|
|
43
45
|
klasses.each do |interactor| # [A, B, C].each do |interactor|
|
44
46
|
interactor.call!(context) # interactor.call!(context)
|
@@ -59,8 +61,10 @@ module Interactify
|
|
59
61
|
# rubocop:enable all
|
60
62
|
|
61
63
|
def attach_klass
|
62
|
-
|
63
|
-
|
64
|
+
name = iterator_klass_name
|
65
|
+
|
66
|
+
namespace.const_set(name, klass)
|
67
|
+
namespace.const_get(name)
|
64
68
|
end
|
65
69
|
|
66
70
|
def namespace
|
@@ -68,7 +72,9 @@ module Interactify
|
|
68
72
|
end
|
69
73
|
|
70
74
|
def iterator_klass_name
|
71
|
-
|
75
|
+
prefix = "Each#{singular_resource_name.to_s.camelize}"
|
76
|
+
|
77
|
+
UniqueKlassName.for(namespace, prefix)
|
72
78
|
end
|
73
79
|
|
74
80
|
def singular_resource_name
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "interactify/unique_klass_name"
|
4
|
+
|
3
5
|
module Interactify
|
4
6
|
class IfInteractor
|
5
7
|
attr_reader :condition, :success_interactor, :failure_interactor, :evaluating_receiver
|
@@ -49,8 +51,9 @@ module Interactify
|
|
49
51
|
# rubocop:enable all
|
50
52
|
|
51
53
|
def attach_klass
|
52
|
-
|
53
|
-
namespace.
|
54
|
+
name = if_klass_name
|
55
|
+
namespace.const_set(name, klass)
|
56
|
+
namespace.const_get(name)
|
54
57
|
end
|
55
58
|
|
56
59
|
def namespace
|
@@ -58,9 +61,10 @@ module Interactify
|
|
58
61
|
end
|
59
62
|
|
60
63
|
def if_klass_name
|
61
|
-
|
64
|
+
prefix = condition.is_a?(Proc) ? "Proc" : condition
|
65
|
+
prefix = "If#{prefix.to_s.camelize}"
|
62
66
|
|
63
|
-
|
67
|
+
UniqueKlassName.for(namespace, prefix)
|
64
68
|
end
|
65
69
|
end
|
66
70
|
end
|
@@ -0,0 +1,72 @@
|
|
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,32 +1,17 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "interactify/interactor_wrapper"
|
4
|
+
|
3
5
|
module Interactify
|
4
|
-
module
|
6
|
+
module Organizer
|
5
7
|
extend ActiveSupport::Concern
|
6
8
|
|
7
9
|
class_methods do
|
8
10
|
def organize(*interactors)
|
9
|
-
wrapped =
|
11
|
+
wrapped = InteractorWrapper.wrap_many(self, interactors)
|
10
12
|
|
11
13
|
super(*wrapped)
|
12
14
|
end
|
13
|
-
|
14
|
-
def wrap_lambdas_in_interactors(interactors)
|
15
|
-
Array(interactors).map do |interactor|
|
16
|
-
case interactor
|
17
|
-
when Proc
|
18
|
-
Class.new do
|
19
|
-
include Interactify
|
20
|
-
|
21
|
-
define_method(:call) do
|
22
|
-
interactor.call(context)
|
23
|
-
end
|
24
|
-
end
|
25
|
-
else
|
26
|
-
interactor
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
15
|
end
|
31
16
|
|
32
17
|
def call
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Interactify
|
4
|
+
module UniqueKlassName
|
5
|
+
def self.for(namespace, prefix)
|
6
|
+
id = generate_unique_id
|
7
|
+
klass_name = :"#{prefix}#{id}"
|
8
|
+
|
9
|
+
while namespace.const_defined?(klass_name)
|
10
|
+
id = generate_unique_id
|
11
|
+
klass_name = :"#{prefix}#{id}"
|
12
|
+
end
|
13
|
+
|
14
|
+
klass_name.to_sym
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.generate_unique_id
|
18
|
+
rand(10_000)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/interactify/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: interactify
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0.pre.alpha.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mark Burns
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-12-
|
11
|
+
date: 2023-12-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: interactor
|
@@ -127,12 +127,14 @@ files:
|
|
127
127
|
- lib/interactify/interactor_wiring/constants.rb
|
128
128
|
- lib/interactify/interactor_wiring/error_context.rb
|
129
129
|
- lib/interactify/interactor_wiring/files.rb
|
130
|
+
- lib/interactify/interactor_wrapper.rb
|
130
131
|
- lib/interactify/job_maker.rb
|
131
132
|
- lib/interactify/jobable.rb
|
132
133
|
- lib/interactify/mismatching_promise_error.rb
|
133
|
-
- lib/interactify/
|
134
|
+
- lib/interactify/organizer.rb
|
134
135
|
- lib/interactify/promising.rb
|
135
136
|
- lib/interactify/rspec/matchers.rb
|
137
|
+
- lib/interactify/unique_klass_name.rb
|
136
138
|
- lib/interactify/version.rb
|
137
139
|
- sig/interactify.rbs
|
138
140
|
homepage: https://github.com/markburns/interactify
|