class Kungfuig::Prepender

Constants

AGRESSIVE_ERRORS

Attributes

method[R]
options[R]
receiver[R]
λ[R]

Public Class Methods

anteponer(*args) click to toggle source
# File lib/kungfuig/prepender.rb, line 32
def anteponer *args
  fail MalformedTarget.new "Factory requires a block; use Prepender#new for more accurate tuning", args unless block_given?
  Prepender.new(*args, &Proc.new).hook!
end
error!(e, **hash) click to toggle source
# File lib/kungfuig/prepender.rb, line 28
def error! e, **hash
  errors << [e, hash]
end
errors() click to toggle source
# File lib/kungfuig/prepender.rb, line 24
def errors
  @errors ||= []
end
new(*args, **params) click to toggle source

Parameters might be: • 1

— method instance
— string in form "Class#method"

• 2

— class (String, Symbol or Class), method name (String, Symbol)
— instance (Object), method name (String, Symbol)
# File lib/kungfuig/prepender.rb, line 47
def initialize *args, **params
   = { before: nil, after: nil, on_hook: nil, on_error: nil }
  @klazz, @method, @receiver =  case args.size
                                when 1
                                  case args.first
                                  when Method then [(class << args.first.receiver ; self ; end), args.first.name, args.first.receiver]
                                  when UnboundMethod then [args.first.owner, args.first.name]
                                  when String
                                    k, m = args.first.split('#')
                                    [k, m && m.to_sym]
                                  end
                                when 2
                                  case args.first
                                  when Module, String then [args.first, args.last.to_sym]
                                  when Symbol then [args.first.to_s.split('_').map(&:capitalize).join, args.last.to_sym]
                                  else
                                    [(class << args.first ; self ; end), args.last.to_sym, args.first]
                                  end
                                end

  @options = params
  after(Proc.new) if block_given? # assign the block to after by default

  fail MalformedTarget.new "Unable to lookup class", args unless @klazz
  fail MalformedTarget.new "Unable to lookup method", args unless @method
end

Public Instance Methods

after(λ = nil)
Alias for: before
before(λ = nil) click to toggle source
# File lib/kungfuig/prepender.rb, line 74
def before λ = nil
  tap { [__callee__] = λ || (block_given? ? Proc.new : nil) }
end
Also aliased as: after, on_hook, on_error
hook!() click to toggle source
# File lib/kungfuig/prepender.rb, line 81
def hook!
  tap { postpone_hook }
end
on_error(λ = nil)
Alias for: before
on_hook(λ = nil)
Alias for: before

Protected Instance Methods

hook() click to toggle source

rubocop:disable Style/NestedTernaryOperator

Calls superclass method
# File lib/kungfuig/prepender.rb, line 107
def hook
  status = {}
  λ = (hash = to_hash).delete(:lambdas)

  p = Module.new do
    include Kungfuig::I★I
    define_method(hash[:method]) do |*args, **params, &cb|
      before_params = hash.merge(receiver: self, ★: args, ★★: params, λ: cb)
      begin
        λ[:before].call(**before_params) if λ[:before]
      rescue => e
        status[:before] = e
        LAMBDA.call λ, e, **hash
      end

      (args.empty? ? (params.empty? ? super(&cb) : super(**params)) : super(*args, **params, &cb)).tap do |result|
        begin
          λ[:after].call(**before_params.merge(result: result)) if λ[:after]
        rescue => e
          status[:after] = e
          LAMBDA.call λ, e, **hash
        end
      end
    end
  end

  klazz.send(:include, Kungfuig) unless klazz.ancestors.include? Kungfuig
  klazz.send(:prepend, p)
rescue => e
  status[:rescued] = e
  raise MalformedTarget.new e.message, "#{@klazz}##{@method}" if AGRESSIVE_ERRORS
ensure
  begin
    λ[:on_hook].call(status) if λ[:on_hook]
  rescue => e
    LAMBDA.call λ, e, reason: :on_hook
  end
end
klazz() click to toggle source
# File lib/kungfuig/prepender.rb, line 87
def klazz
  return @klazz if @klazz.is_a?(Module)
  @klazz = Kernel.const_get(@klazz) if Kernel.const_defined?(@klazz)
  @klazz
end
postpone_hook() click to toggle source

rubocop:enable Style/NestedTernaryOperator

# File lib/kungfuig/prepender.rb, line 147
def postpone_hook
  return hook if ready?

  TracePoint.new(:end) do |tp|
    if tp.self.name == @klazz && ready?
      hook
      tp.disable
    end
  end.enable
end
ready?() click to toggle source
# File lib/kungfuig/prepender.rb, line 93
def ready?
  @receiver && @receiver.respond_to?(@method) ||
    klazz.is_a?(Module) && klazz.instance_methods.include?(@method)
end
to_hash() click to toggle source
# File lib/kungfuig/prepender.rb, line 98
def to_hash
  {
    klazz: klazz.to_s,
    method: @method,
    lambdas: 
  }
end