module Ducktape

Although against sematinc versioning recommendation, while version is < 1.0.0, an increase in the minor version number may represent an incompatible implementation with the previous minor version, which should have been represented by a major version number increase.

Constants

VERSION

Public Class Methods

def_hookable(klass, *args) click to toggle source
# File lib/ducktape/ext/def_hookable.rb, line 5
def self.def_hookable(klass, *args)
  return if args.length == 0
  names_hash = args.extract_options!

  # reversed merge because names_hash has priority
  @hookable_types[klass] = Hash[args.flatten.map { |v| [v, v] }].merge!(names_hash)

  nil
end
hookable(obj) click to toggle source
# File lib/ducktape/ext/def_hookable.rb, line 15
def self.hookable(obj)
  return obj if obj.is_a?(Hookable)
  m = obj.class.ancestors.find { |c| @hookable_types.has_key?(c) }
  return obj unless m
  obj.singleton_class.send :include, Hookable
  obj.singleton_class.make_hooks(@hookable_types[m])
  obj
end

Public Instance Methods

bindable_attrs() click to toggle source
# File lib/ducktape/bindable.rb, line 127
def bindable_attrs
  @bindable_attrs ||= {}
end
build_hook(hook) click to toggle source
# File lib/ducktape/hookable.rb, line 157
def build_hook(hook)
  case hook
    when Proc, Method then hook
    when Symbol, String then caller.method(hook)
    else hook.method(:call)
  end
end
call_handlers(event, *args) click to toggle source

‘#call_handlers` is similar to `#call_hooks`, but stops calling other hooks when a hook returns a value other than nil or false. If caller is a Hash, then use: call_*s(event, hash, {})

# File lib/ducktape/hookable.rb, line 181
def call_handlers(event, *args)
  invoke :handler, event, *args
end
call_hook(hook, event, caller, parms, parms2) click to toggle source
# File lib/ducktape/hookable.rb, line 165
def call_hook(hook, event, caller, parms, parms2)
  return hook.(), parms2 if hook.arity == 0
  return hook.(event, caller, parms) if hook.arity > 1

  parms = parms.to_h if parms.is_a?(OpenStruct)
  parms2 ||= OpenStruct.new(parms.merge(event: event, caller: caller))
  [ hook.(parms2), parms2 ]
end
call_hooks(event, *args) click to toggle source
# File lib/ducktape/hookable.rb, line 174
def call_hooks(event, *args)
  invoke :hook, event, *args
end
extract_parameters(args) click to toggle source
# File lib/ducktape/hookable.rb, line 142
def extract_parameters(args)
  raise ArgumentError, "wrong number of arguments (#{args.length} for 0..2)" if args.length > 2

  case
    when args.length == 0                               # call_*s(event, caller = self, parms = {})
      [self, {}]
    when args.length == 2                               # call_*s(event, caller, parms)
      args
    when [Hash, OpenStruct].include?(args[0].class)     # call_*s(event, caller = self, parms)
      [self, args[0]]
    else
      [args[0], {}]                                     # call_*s(event, caller, parms = {})
  end
end
get_bindable_attr(name) click to toggle source
# File lib/ducktape/bindable.rb, line 131
def get_bindable_attr(name)
  raise AttributeNotDefinedError.new(self.class, name.to_s) unless bindable_attr?(name)
  bindable_attrs[name.to_s] ||= BindableAttribute.new(self, name)
end
invoke(type, event, *args) click to toggle source
# File lib/ducktape/hookable.rb, line 185
def invoke(type, event, *args)
  caller, parms = extract_parameters(args)
  return unless hooks.has_key?(event.to_s)
  handled, parms2 = nil, nil
  hooks[event.to_s].each do |hook|
    hook = build_hook(hook)
    handled, parms2 = call_hook(hook, event, caller, parms, parms2)
    break if type == :handler && handled
  end
  type == :handler && handled
end
metadata(name) click to toggle source
# File lib/ducktape/bindable.rb, line 119
def metadata(name)
  is_a?(Class) ? singleton_class.metadata(name) : self.class.metadata(name)
end
set_value(attr_name, value, &block) click to toggle source
# File lib/ducktape/bindable.rb, line 123
def set_value(attr_name, value, &block)
  get_bindable_attr(attr_name).set_value(value, &block)
end