I had not found any well-known description for Interactors. For example, Interactor gem’s README provides following characteristic:
An interactor is a simple, single-purpose object. Interactors are used to encapsulate your application’s business logic. Each interactor represents one thing that your application does.
Looking at interactor gem and also Hanami::Interactor I’ve built my image of interactors accordingly to following principles:
So, this writing is dedicated to implementing interactor in the simplest of possible ways.
First, let’s write the example part of the code that will use interactor logic.
This code calls FetchFeedbacks service class and then redirects or shows error messages accordingly to the result of the call. This is how should interactor work in my opinion. Now let’s imagine, how what exactly should FetchFeedbacks class be to meet our conditions.
We had already put interactor logic into separate
Interactor module, thus all the classes including that mixin would have
call method we validate input parameters, and if the condition is not met, we add error to interactor object’s errors. In a successful scenario, some background job named
PostFeedbacks is launched. In both scenarios,
self is returned. It’s worthful to note, that we are not limited to return the only that slim object,
containing success or failure status. We also can set custom instance variables for each object. Including Interactor module should only assure that we can call
add_error methods on the resulting object.
But we have not written Interactor module yet. Let’s continue with writing specs for the FetchFeedbacks class. BTW I’m not a huge fan of writing tests for non-existent code, but in this case, we would benefit from doing this, because it would help us to have a clean representation of how Interactor module should be designed. Also, some people would say, that we should write specs for Interactor module itself, but I think that writing specs for collaborator class can show us Interactor requirements more clearly.
Now, let’s make tests green.
This implementation successfully passes all tests. Someone might ask “what’s the point of using wrapper method
add_error, if we still have a possibility of using
+ methods on object’s
This method added to provide custom error raising logic. If we want to manage errors array directly, this does not break any functionality, because any interactor object that has errors will remain in the failed status.