How to create services using Active Interactions in Rails

Mateo mojica
3 min readOct 13, 2023

--

Photo by Erik Mclean on Unsplash

When you are building applications, you often find yourself using the same logic over and over again in different sections of your code. One of the ways to reuse your code is to abstract them into services so they can be used in different parts of your application. In this article, I’m going to show you a way to create those services easily while keeping your code organized.

You might be asking why to use services, and the advantages are several. One of them is that it aligns with the DRY(don’t repeat yourself) principle, which allows you to reduce the amount of code that you have in your application. Another advantage is that it keeps business logic isolated from other types of logic, making it easier to read and debug. And the last one is that it centralizes your code so it will be easier to maintain, so if you have a service that is used in ten different places and you need to make a change, you only change the code for the interaction and that is it, instead of having to go through ten places implementing the same change.

To create services in Rails there is a gem that allows you to separate your business logic in an easy way, that gem is called Active Interaction. ActiveInteraction manages application-specific business logic. It’s an implementation of service objects designed to blend seamlessly into Rails. It also helps you write safer code by validating that your inputs conform to your expectations.

Photo by Den Harrson on Unsplash

One of the advantages that active interactions provide out of the box is type validation for your arguments. The first thing you define when creating an active interaction are the arguments that the service will receive, you can specify a name, a type, and a default value, and if it is required or not, you can also set a description to help document your service in an easy way. You can have regular types like integer, float, boolean, and string, but you can also have more advanced types like record, hash, array, file, and object, giving your service the flexibility for processing pretty much anything that you will need. You can also use the same validation methods that you get on a model for your arguments, but those are provided by Active model and not by the interaction so they will be executed separately.

You have two options to execute your service and get the results, the first one is the .run method, which will run your active interaction and return an object with everything related to the execution of it. That object will have a result section, and an error section and it will have the helper method .valid? to check immediately if the service got a positive outcome or had any errors, and like any other result on Rails if there are errors check the error section of the outcome if not check the result section of the outcome.

outcome = Square.run(x: 'two point one')
outcome.valid?
# => nil
outcome.errors.messages
# => {:x=>["is not a valid float"]}

outcome = Square.run(x: 2.1)
outcome.valid?
# => true
outcome.result
# => 4.41

The second way of executing an interaction is with the .run! Method and it will run the interaction normally but the difference is in the way the outcome is presented, in this case, if the interaction has a valid outcome it will return the result but if it is invalid it will raise an error that you have to catch in your code to prevent it from breaking.

Square.run!(x: 'two point one')
# ActiveInteraction::InvalidInteractionError: X is not a valid float
Square.run!(x: 2.1)
# => 4.41

This was a short article that I wanted to share with you to expand your toolkit when working with Rails. Thank you for reading it all the way through and if you liked it give it a clap. Also, check out my other articles on various topics and follow my profile to get notified when I publish new articles.

References

--

--

Mateo mojica
Mateo mojica

Written by Mateo mojica

Electronic engineer and software developer

No responses yet