Skip to content

Commit 2a0275a

Browse files
authored
apply proof reading suggestions (#5)
1 parent a160714 commit 2a0275a

File tree

1 file changed

+33
-73
lines changed

1 file changed

+33
-73
lines changed

README.md

+33-73
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,6 @@
11
# Interactify
22

3-
[Interactors](https://github.com/collectiveidea/interactor) are a great way to encapsulate business logic in a Rails application.
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.
134
## Installation
145

156
```ruby
@@ -46,6 +37,8 @@ expect(described_class).to promise_outputs(:fee, :fi, :fo, :fum)
4637

4738
### Syntactic Sugar
4839
- 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.
4942
- Concise syntax for most common scenarios with `expects` and `promises`. Verifying the presence of the keys/values.
5043
- Automatic delegation of expected and promised keys to the context.
5144

@@ -66,7 +59,6 @@ class LoadOrder
6659
required(:order).filled
6760
end
6861

69-
7062
def call
7163
context.order = Order.find(context.id)
7264
end
@@ -92,8 +84,8 @@ end
9284

9385
### Lambdas
9486

95-
With vanilla interactors, it's not possible to use lambdas in organizers, and sometimes we only want a lambda.
96-
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.
9789

9890
```ruby
9991
organize LoadOrder, ->(context) { context.order = context.order.decorate }
@@ -160,7 +152,6 @@ class DoSomethingWithOrder
160152
end
161153
```
162154

163-
164155
```ruby
165156
# after
166157
class OuterOrganizer
@@ -181,7 +172,6 @@ class LoadOrder
181172
end
182173
end
183174

184-
185175
class DoSomethingWithOrder
186176
# ... boilerplate ...
187177
def call
@@ -190,7 +180,7 @@ class DoSomethingWithOrder
190180
end
191181
```
192182

193-
### Conditionals (if/else)
183+
### Conditionals (if/else) with lambda
194184

195185
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.
196186

@@ -215,7 +205,6 @@ class InnerThing
215205
end
216206
```
217207

218-
219208
```ruby
220209
# after
221210
class OuterThing
@@ -224,10 +213,9 @@ class OuterThing
224213
SetupStep,
225214
self.if(->(c){ c.thing == 'a' }, DoThingA, DoThingB),
226215
end
227-
228216
```
229217

230-
### More Conditionals
218+
### Conditionals with a key from the context
231219

232220
```ruby
233221
class OuterThing
@@ -351,19 +339,19 @@ class SomeInteractor
351339
# ...
352340
end
353341
end
354-
355-
clsas SomeInteractorJob
356-
include Sidekiq::Job
357-
358-
def perform(*args)
359-
SomeInteractor.call(*args)
360-
end
361-
end
362342
```
363343

364344
```diff
365-
-SomeInteractor.call(*args)
366-
+SomeInteractorJob.perform_async(*args)
345+
- SomeInteractor.call(*args)
346+
+ class SomeInteractorJob
347+
+ include Sidekiq::Job
348+
+
349+
+ def perform(*args)
350+
+ SomeInteractor.call(*args)
351+
+ end
352+
+ end
353+
+
354+
+ SomeInteractorJob.perform_async(*args)
367355
```
368356

369357
```ruby
@@ -380,17 +368,15 @@ end
380368
No need to manually create a job class or handle the perform/call impedance mismatch
381369

382370
```diff
383-
-SomeInteractor.call!(*args)
384-
+SomeInteractor::Async.call!(*args)
371+
- SomeInteractor.call!(*args)
372+
+ SomeInteractor::Async.call!(*args)
385373
```
386374

387375
This also makes it easy to add cron jobs to run interactors. As any interactor can be asyncified.
388376
By using it's internal Async class.
389377

390378
N.B. as your class is now executing asynchronously you can no longer rely on its promises later on in the chain.
391379

392-
393-
394380
## FAQs
395381
- This is ugly isn't it?
396382

@@ -406,59 +392,33 @@ class OuterOrganizer
406392
)
407393
end
408394
```
395+
1. Do you find the syntax of OuterOrganizer ugly?
409396

410-
Yes I agree. It's early days and I'm open to syntax improvement ideas. This is really about it being conceptually less ugly than the alternative, which is to jump around between lots of files. In the existing alternative to using this gem the ugliness is not within each individual file, but within the overall hidden architecture and the hunting process of jumping around in complex interactor chains. We can't see that ugliness but we probably experience it. If you don't feel or experience that ugliness then this gem may not be the right fit for you.
411-
412-
413-
- Is this interactor/interactor-contracts compatible?
414-
-
415-
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.
416-
417-
418-
- Why not propose changes to the interactor or interactor-contracts gem?
419-
420-
Honestly, I think both are great and why we've built on top of them.
421-
I presume they'd object to such an extensive opinionated change, and I think that would be the right decision too.
422-
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.
397+
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.
423398

424-
- Isn't this all just syntactic sugar?
399+
2. Is this compatible with interactor/interactor-contracts?
425400

426-
Yes, but it's sugar that makes the code easier to read and understand.
401+
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.
427402

428-
- Is it really easier to parse this new DSL/syntax than POROs?
429-
430-
That's subjective, but I think so. The benefit is you have fewer extraneous files patching over a common problem in interactors.
403+
3. Why not suggest enhancements to the interactor or interactor-contracts gems?
431404

432-
- But it gets really verbose and complex!
433-
434-
Again this is subjective, but if you've worked with apps with hundred or thousands of interactors, you'll have encountered these problems.
435-
I think when we work with interactors we're in one of two modes.
436-
Hunting to find the interactor we need to change, or working on the interactor we need to change.
437-
This makes the first step much easier.
438-
The second step has always been a great experience with interactors.
405+
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.
439406

440-
- I prefer Service Object
441-
442-
If you're not heavily invested into interactors this may not be for you.
443-
I love the chaining interactors provide.
444-
I love the contracts.
445-
I love the simplicity of the interface.
446-
I love the way they can be composed.
447-
I love the way they can be tested.
407+
4. Is this just syntactic sugar?
448408

449-
When I've used service objects, I've found them to be more complex to test and compose.
450-
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+
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.
451410

452-
## Development
411+
5. Is the new DSL/syntax easier to understand than plain old Ruby objects (POROs)?
453412

454-
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
413+
This is subjective, but we believe it is. It reduces the need for numerous files addressing common interactor issues, thereby streamlining the workflow.
455414

456-
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
415+
6. Doesn't this approach become verbose and complex in large applications?
457416

458-
## Contributing
417+
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.
459418

460-
Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/interactify.
419+
7. What if I prefer using Service Objects?
461420

421+
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.
462422
## License
463423

464424
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).

0 commit comments

Comments
 (0)