History: The earliest prototype - marian13/convenient_service GitHub Wiki

##
# service.rb
#
class Service
  class UndeterminedServiceResultError < StandardError; end

  def initialize(**kwargs); end

  def self.call(**kwargs)
    result = self.new(**kwargs).call

    if result.instance_of?(SuccessfulResult) || result.instance_of?(FailedResult)
      yield result if block_given?

      result
    else
      self.raise_undetermined_service_result_error
    end
  end

  def self.raise_undetermined_service_result_error
    message =
      "#{self} service did NOT return SuccessfullResult or FailedResult instance. " \
      "Probably, you have forgotten to call `success!` or `failure!`?"

    raise UndeterminedServiceResultError, message
  end

  def success!(**kwargs)
    SuccessfulResult.new(kwargs)
  end

  def failure!(**kwargs)
    FailedResult.new(kwargs)
  end
end
##
# service/failed_result.rb
#
class Service
  class FailedResult
    attr_reader :errors

    def initialize(errors = {})
      @errors = errors
    end

    def successful?
      false
    end

    def failed?
      true
    end

    def values
      {}
    end
  end
end
##
# service/successful_result.rb
#
class Service
  class SuccessfulResult
    attr_reader :values

    def initialize(values = {})
      @values = values
    end

    def successful?
      true
    end

    def failed?
      false
    end

    def errors
      {}
    end
  end
end