In part 1 of this series we've looked on the basics of the interactor pattern, created an interactor dealing with the Mailgun API and refactored it to use a Result class to signalize success and failure.
In this part, we want to add some method sugar to our solution, so that we don't have to deal with the setup process too much.

Let's start with the interactor we created last time:

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

  pattr_initialize :domain

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

  private

  # Other parts omitted
end

Instead of calls to Result#newI would rather like to use something closer to natural language, like fail, or errored. Let's try that: We'll refactor CreateMailgunDomain#call to sound nicer:

def call
  response = post('/domains', name: domain)
  if response.code == 200
    response
  else
    fail!(response)
  end
end  

That looks better, in my opinion. If the call to the /domains endpoint is successful (meaning if it returns a 200 OK), we will return the response. If it weren't, we would call fail!. Please note that in Ruby, fail is a reserved word and used as a synonym to raise.

If we run that code now, it would fail because we haven't implemented our fail! method yet. Let's do that:

def fail!(object = nil)
  fail Failure, object
end

class Failure < StandardError
  attr_reader :object

  def initialize(object = nil, message = nil)
    super(message)
    @object = object
  end
end

We will just call the ordinary fail method with a new Failure object. Failure takes and optional object (our response) and an optional message, which it inherits from StandardError.

Now, how do we get this code into our CreateMailgunDomain interactor? There are various options for that: we could create an Interactor class and let our custom interactor inherit from it. Or we could create a module which we can include into our interactor. For this article, I'll go with solution #2, the module:

module Interactor
  def self.included(base)
    base.extend(ClassMethods)
  end

  def fail!(object = nil)
    self.class.fail!(object)
  end

  module ClassMethods
    def call(*args)
      object = new(*args).call
      Result.new(true, object)
    rescue Failure => failure
      Result.new(false, failure.object)
    end

    def fail!(object = nil)
      fail Failure, object
    end
  end
end

What the call method does is, it creates a new instance of the class it was included in and calls call on the instance. If the instance returns a value, it wraps that one in a new instance of the Result class, sets the success attribute to true (via the constructor) and returns it.

If during the processing a Failure error is raised, it will also create a new instance of the Result class, but set its success attribute to false and return it along with the object from the failure.

We also added a new instance method onto the class, called fail!. That's the once which is called by our CreateMailgunDomain interactor above. It just passes the arguments it receives on to the same-name class method.

If you're unsure what's happening with the internal ClassMethods module, please check out this article here: Include vs Extend in Ruby.

Now we can finally include this module in our interactor and use it:

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

  pattr_initialize :domain

  def call
    response = post('/domains', name: domain)
    if response.code == 200
      response
    else
      fail!(response)
    end
  end

  private

  # Other parts omitted
end

# Use it like so:
CreateMailgunDomain.call('example.com')

If you are interested in the complete code, I've created a Gist with all the parts put together.

Alright, that's it for today! I hope you enjoyed this two-part article about interactors. As always, I'm happy for feedback and new ideas - just leave a comment!