Sha256: b96e833901b006aee2173b6e28bf124fe7dd19caa47136e1fc7f9d580b326850

Contents?: true

Size: 1.47 KB

Versions: 1

Compression:

Stored size: 1.47 KB

Contents

require "active_model"

class Servizio::Service
  include ActiveModel::Model
  include ActiveModel::Validations

  attr_accessor :result

  OperationNotCalledError = Class.new(StandardError)

  # http://stackoverflow.com/questions/14431723/activemodelvalidations-on-anonymous-class
  def self.name
    super ? super : "__anonymous_servizio_service_class__"
  end

  def result
    called? ? @result : (raise OperationNotCalledError)
  end

  def called?
    @called == true
  end

  def failed?
    called? && errors.present?
  end

  def succeeded?
    called? && errors.blank?
  end

  #
  # This code does some metaprogramming magic. It overwrites .new, so that every
  # instance of a class derived from Servizio::Service, gets a module prepended
  # automatically. This way, one can easily "wrap" the methods, e.g. #call.
  #
  module MethodDecorators
    module Call
      def call
        if valid?
          self.result = super
          @called = true
        else
          @called = false
        end

        self
      end
    end

    def inherited(subclass)
      subclass.instance_eval do
        alias :original_new :new

        def self.inherited(subsubclass)
          subsubclass.extend(Servizio::Service::MethodDecorators)
        end

        def self.new(*args, &block)
          (obj = original_new(*args, &block)).singleton_class.send(:prepend, Servizio::Service::MethodDecorators::Call)
          return obj
        end
      end
    end
  end

  extend MethodDecorators
end

Version data entries

1 entries across 1 versions & 1 rubygems

Version Path
servizio-0.1.0 lib/servizio/service.rb