The other day I was working on a Rails application that did some communication with the Mailgun API. I already started with a light version of the interactor pattern but soon discovered that I wanted to have not only the hard work of
calling the API done in my interactor pattern, but also make the decision if the call was successful or not.

What I started with was this:

class CreateMailgunDomain
  include HTTParty
  base_uri 'api.mailgun.com'

  pattr_initialize :domain

  def call
    post('/domains', name: domain)
  end

  private

  def post(path, options)
    RestClient.post("#{base_url}#{path}", options)
  end

  def base_url
    "https://api:#{api_key}@api.mailgun.net/v3"
  end

  def api_key
    ENV['MAILGUN_API_KEY']
  end
end

We'll use this like so:

class SettingsController < ApplicationController
  def create
    CreateMailgunDomain.new(params[:domain]).call
    render head: :ok
  end
end

Now, what happens if the call to Mailgun fails, because we've lost network connectivity, or Mailgun's API is down? Also, what happens if
our request goes through, but the API returns an error because we've already registered the domain with Mailgun?

My first approach was to handle that case in the controller:

class SettingsController < ApplicationController
  def create
    result = CreateMailgunDomain.new(params[:domain]).call
    if result.code == 200
      render head: :ok
    else
      render head: 500
    end
  end
end

This solution now at least allows us to handle error cases. We would still need to guard against an exception being thrown by RestClient, but you get the idea. But is it a good idea to separate know-how of the way Mailgun's API works, splitting the part where we assemble the request from the part where we handle it? I would love to have these two in the same place so that we can also reuse the CreateMailgunDomain interactor in other classes.

class Result < SimpleDelegator
  def initialize(success, object = nil)
    @success = success
    super(object)
  end

  def success?
    @success
  end

  def failure?
    !@success
  end
end

class CreateMailgunDomain
  include HTTParty
  base_uri 'api.mailgun.com'

  pattr_initialize :domain

  def call
    result = post('/domains', name: domain)
    if result.code == 200
      Result.new(true, result)
    else
      Result.new(false, result)
    end
  end

  private

  # Other parts omitted
end

class SettingsController < ApplicationController
  def create
    result = CreateMailgunDomain.new(params[:domain]).call
    if result.success?
      render head: :ok
    else
      render head: 500
    end
  end
end

I've added the Result class to the mix, which offers two instance methods: Result#success? and Result#failure?. It also inherits from SimpleDelegator, which gives forwards messages from an instance of Result to the underlying object which we pass in the constructor.

In part 2 I will refactor our CreateMailgunDomain class a bit so that we move the common interactor parts into a separate module to be able to reuse them easily. I'll also add some syntactic sugar to it so that we can use two methods (success! and fail!) so signal success and failure, respectively.

Until next time and let me know what you think in the comments below!

Part 2 is now online, continue here.