Open michaelherold opened 4 years ago
Interested and willingg to contribute where do we start?
That's a basic frame that gets everything set up how you need it to test. You'll have access to an organizer
that responds to .organized
that gets a set of interactors. Each of those interactors has a contract
that you'll have to figure out how to combine to see if they match the overarching contract
on the organizer
.
I'm not sure how this will work but it seems like something we should be able to do.
Feel free to add whatever code you feel you need. Ideally, it won't cause any backward-compatibility problems. If it does cause anything else in the test suite to fail we can work through those issues.
Let me know if you have any further questions!
Oh I've just seen this. I don't know how I missed this issue.
We implemented this internally as a spec that validates all organizers and even nested organizers and outputs a useful error message for failures.
Example failure:
Failure/Error:
expect(interactor).to be_nil, <<~ERROR
Organizer:
#{organizer.filename}
#{organizer.klass}
Interactor:
#{interactor.filename}
#{interactor.klass}
Interactor contains expected keys:
Organizer:
/home/mark/code/thing/app/interactors/thing.rb
Thing
Interactor:
/home/mark/code/thing/app/interactors/some_other_thing.rb
SomeOtherThing
Interactor contains expected keys:
[:some_thnig_with_a_typo]
that are not previously defined in the Organizer or any of its interactors' promises
We've also done some things that help with readability (for us) for defining contracts.
E.g.
include InteractorContracts
expect :foo, filled: true # defaults to true
expect :baz, filled: false
and it removes quite a bit of the boilerplate.
Not sure if you'd want the spec based approach to validation? The spec support file itself has some pretty hairy metaprogramming going on to find all our interactors and even nested interactors of the following kind. It works with heavily namespaced code too.
class SomeOrganizer
include InteractorOrganizer
class A
include InteractorContracts
expect :foo
end
class B
include InteractorContracts
expect :bar
end
organize A, B
end
By the way, we have been using these changes with our production test suite now for about six months.
If either of these things are of interest, I can try and pull together PR(s). I see you set a high bar with your code quality! I may throw together a draft PR and you can critique at will until it meets your standards.
@michaelherold
I ended up open sourcing https://github.com/markburns/interactify that depends on interactor-contracts
It's extracted from a large Rails app. It's optionally Rails > 6, ruby > 3.1.4, ~with sidekiq only~sidekiq optional. ~at the moment, but I'm open to making it a bit more pluggable if there's an appetite for it~ .
Also if there's any of this you'd want to pull in/support here upstream, I'd be glad to look into pulling something together.
No worries if not, it's definitely an opinionated approach.
My original vision for this gem was to build a way to validate that the the interactors that you compose with organizers form a valid chain of business logic. When I used interactors, I would end up writing a ton of integration tests to make sure the chain of logic all fit together and to protect against regressions.
I thought it would be cool to do something like this:
The
validate_organizers!
method would act like FactoryBot's linting capabilities. We could make it part of the test suite or we could make a Rake task out of it. Whatever feels like the best experience.The idea is that, given the list of interactors passed to
organize
, we could compare the promises and expectations of the organized interactors plus the contracts of the organizer itself to check whether it's a valid organizer.I'm happy to mentor anyone willing to take this on. I do not currently use interactors in my work, hence why I haven't implemented this myself. But for people who use the Interactor gem, I think this would be a major benefit.