The Interactor gem is a powerful tool that simplifies the implementation of workflows in Ruby applications. By breaking down tasks into smaller components, known as interactors, and utilizing the context for data sharing, we can simplify business logic and improve code maintainability. In this blog post, we’ll explore how interactors can simplify business logic by implementing order fulfillment for an e-commerce application.
For this, we’ll create two interactors: ValidateCart
and ProcessPayment
.
The ValidateCart
interactor is responsible for validating the shopping cart. It contains the logic to perform this validation and, if the cart is considered valid, sets the cart_valid
variable to true
in the interactor’s context
. Otherwise, it fails with an error message indicating that the cart is invalid.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class ValidateCart
include Interactor
def call
# Logic to validate the shopping cart
if valid_cart?
context.cart_valid = true
else
context.fail!(message: "The shopping cart is invalid.")
end
end
private
def valid_cart?
# Check if the shopping cart is valid
end
end
The ProcessPayment
interactor is responsible for processing the payment for the order. It checks if the cart_valid
variable is true
in the context
, indicating that the cart has been successfully validated by the previous interactor. If so, it performs the payment processing logic and sets the payment_processed
variable to true
in the context
. Otherwise, it fails with an error message stating that it’s not possible to process the payment without a valid shopping cart.
1
2
3
4
5
6
7
8
9
10
11
12
class ProcessPayment
include Interactor
def call
if context.cart_valid
# Logic to process the payment for the order
context.payment_processed = true
else
context.fail!(message: "Cannot process payment without a valid shopping cart.")
end
end
end
Using the Interactors
Now that we have our interactors defined, we can use them to finalize an order. Let’s see how this can be done:
1
2
3
4
5
6
7
8
9
10
11
result = ValidateCart.call
if result.success?
result = ProcessPayment.call(result.context)
if result.success?
puts "Order processed successfully!"
else
puts "Error processing payment: #{result.message}"
end
else
puts "Error validating the shopping cart: #{result.message}"
end
In this example, we call the ValidateCart
interactor and check if the execution was successful. If it is, we call the ProcessPayment
interactor, passing the returned context. We then check if the payment processing was successful and display the appropriate message accordingly.