Often when working with Rails we hear about fatty controllers and skinny models. We also come across complex user interactions where we need to perform tasks sequentially on particular user action.

There are various ways to solve the above problems using service objects, form objects, policy objects, etc.

One such way to refactor code is to use Interactor gem.

We need to add the interactor gem in our Gemfile and execute bundle install

#### Interactors

As seen in the above example

• We created a small class AddNumbers and included Interactor in the class.

• We passed two arguments to call method a and b. They can be accessed inside the interactor using the context object as context.a and context.b.

• We also set the sum inside the context using context.sum = context.a + context.b.

• Basically context contains everything the interactor needs to do its work.

• AddNumbers.call(a: 1, b: 2) returns a context object and we can check if the above code executed successfully or not by checking result.failure?

• We can check the sum by executing result.sum

• If something goes wrong in the interactor we can flag the context as failed by context.fail! and also set the error message as context.fail!(error: "Error message"). Above example can be modified as

The interactor also provides before, around and after hooks. We can think of them to be similar to before_action, around_action and after_action used in controllers.

To avoid rescue in the above example we can add a before hook to check if the numbers are integer or not and fail the context accordingly. We can initialize sum to 0 as shown below.

The above interactor is a single-purpose unit interactor. A complex system might involve multiple interactors which need to be called in a sequence.

#### Organizers

To execute a sequence of interactors we can use organizers provided by this gem. Imagine a situation where we need to pull data of users from different social media accounts and import it into our database.

The basic steps we might follow to import the users will be:

• Fetch data from the social media account.
• Convert data into standard format which can be imported to our system.
• Import data into our system.

Each of the above steps can be seen as a single unit and we can create interactors for each step. The above steps can be grouped in an organizer as below:

We have created three interactors inside ImportSocialMediaUsers organizers. The three interactors will be called one after another in a sequence.

If any interactor fails then next interactors are not called and the respective error is returned.

So to check if the flow was executed successfully we can use #success? or #failure? method as below

As per the above example, we observe Facebook.new is passed as a client to the organizer ImportSocialMediaUsers.

So our Facebook class will look like this

If we decide to integrate Twitter, and import users from Twitter we just need to implement the Twitter class and pass its instance to the ImportSocialMediaUsers organizer as below:

The interactor and organizers help to refactor the code into smaller single units making them easily testable and reusable.