Using interactors in Rails


Interactor gem

Let’s do a quick review.

What is an Interactor?

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.

Context

An interactor is given a context. The context contains everything the interactor needs to do its work.

When an interactor does its single purpose, it affects its given context.

Let’s get started!

gem "interactor", "~> 3.0"

Implementation

Here, we’re setting up something like steps of interactors to follow.

Here we’re using OrderInit and AddLog interactors, that means our flow will follow this chain.

class AddOrder
  include Interactor::Organizer

  organize OrderInit, AddLog
end

On the controller level, let’s call our AddOrder organizer and pass order_params as a parameter.

def create
  @order = Order.new(order_params)
  result = AddOrder.call(order_params)
  return render status: :bad_request, json: result.error unless result.success?
  render status: :ok, json: result.order
end

Well, easy part: OrderInit should contain call method which uses context as parameter.

Let’s add simple validations here (we can call fail on context).

class OrderInit
  include Interactor

  def call
    context.fail!(error: 'Please add title') if context[:title].empty?

    order = Order.create(title: context[:title], total_price: context[:total_price])
    context.fail! unless order.valid?
    
    context.order = order
  end
end

Last step is AddLog interactor, here we just showing log message for the order, using context.

class AddLog
  include Interactor

  def call
    Rails.logger.info("ADDING ORDER WITH TOTAL PRICE: #{context[:total_price]}")
  end
end

That’s it! Easy and simple.