class Decouple::Decoupler

Public Class Methods

new(klass, &block) click to toggle source

@param klass [Class] A class to decouple @yield Decoupling block

# File lib/decouple/decoupler.rb, line 6
def initialize(klass, &block)
  @klass = klass
  instance_eval(&block) if block
end

Public Instance Methods

on(action, &block) click to toggle source

@param action [Symbol] Name of the method being decoupled @yield Method body extension

# File lib/decouple/decoupler.rb, line 13
def on(action, &block)
  if has_key?(action)
    raise ArgumentError, "#{action} action is already callbacked"
  end

  unless @klass.instance_methods.include?(action)
    raise ArgumentError, "No such action #{action}"
  end

  self[action] = block
end
run(klass_instance, *arguments) click to toggle source

Runs callbacks (decouplings) attached to decoupling methods @param klass_instance [Object] An object where the decoupling will be called @param arguments [Array]

# File lib/decouple/decoupler.rb, line 28
def run(klass_instance, *arguments)
  unless klass_instance.is_a?(@klass)
    raise ArgumentError, "Running #{klass_instance.class.name} on #{@klass.name} Decoupler"
  end

  action = nil
  depth = 0 # Can be optimized by seeting to 3

  while action.nil?
    location = caller_locations(depth+=1, 1)[0] or raise "No action to proceed (invalid context) [#{depth}]"
    location = location.label.to_sym
    action = location if self[location]
  end

  run_on(klass_instance, action, *arguments)
end
run_on(klass_instance, action, *arguments) click to toggle source

Runs callback attached to method @param klass_instance [Object] An object where the decoupling will be called @param action [Symbol, String] Name of decoupled method

# File lib/decouple/decoupler.rb, line 48
def run_on(klass_instance, action, *arguments)
  block = self[action.to_sym] or raise ArgumentError, "No callback for #{action}"
  klass_instance.instance_exec(*arguments, &block)
end