module Ducktape::Hookable::ClassMethods

Public Instance Methods

def_hook(event) click to toggle source

Creates a wrapper method for add_hook that doesn’t require the event to be passed. For example, calling:

def_hook :on_init

will create a on_init method, that can be used as:

on_init { |*_| puts 'I initialized' }

It’s the same as calling:

add_hook(:on_init) { |*_| puts 'I initialized' }
# File lib/ducktape/hookable.rb, line 43
def def_hook(event)
  define_method event, ->(method_name = nil, &block) do
    add_hook event, method_name, &block
  end
end
def_hooks(*events) click to toggle source

Calls def_hook for each event passed.

# File lib/ducktape/hookable.rb, line 50
def def_hooks(*events)
  events.each { |event| def_hook(event) }
end
make_handlers(*args) click to toggle source

Overrides (decorates) existing methods to make then handleable. This is similar to hookable, but stops calling the hooks when a hook returns false or nil.

# File lib/ducktape/hookable.rb, line 62
def make_handlers(*args)
  make :handler, *args
end
make_hooks(*args) click to toggle source

Overrides (decorates) existing methods to make then hookable.

# File lib/ducktape/hookable.rb, line 55
def make_hooks(*args)
  make :hook, *args
end

Private Instance Methods

build_hook_names(args) click to toggle source
# File lib/ducktape/hookable.rb, line 79
def build_hook_names(args)
  hook_names = args.extract_options!

  #Reversed merge because hook_names has priority.
  Hash[args.flatten.map { |v| [v, v] }].merge!(hook_names)
end
decorate_method(type, original_method, hook_name) click to toggle source
# File lib/ducktape/hookable.rb, line 86
def decorate_method(type, original_method, hook_name)
  define_method(original_method.name) do |*args, &block|
    bound_method = original_method.bind(self)
    result = bound_method.(*args, &block)
    params = OpenStruct.new(args: args, method: original_method.name, result: result)
    call_name = "call_#{ type }s"
    hook_result = send(call_name, hook_name, self, params)
    unless hook_result && type == :handler
      # invoke if previous call is false or nil
      send call_name, :on_changed, self, params
    end
    result
  end
end
make(type, *args) click to toggle source
# File lib/ducktape/hookable.rb, line 68
def make(type, *args)
  return if args.length == 0

  build_hook_names(args).each do |method_name, event|
    hook_name = "on_#{event}"
    def_hook(hook_name) unless method_defined?(hook_name)
    original_method = public_instance_method(method_name)
    decorate_method type, original_method, hook_name
  end
end