Module: HaveAPI::Hooks
- Defined in:
- lib/haveapi/hooks.rb
Overview
All registered hooks and connected endpoints are stored in this module.
It supports connecting to both class and instance level hooks. Instance level hooks inherit all class registered hooks, but it is possible to connect to a specific instance and not for all instances of a class.
Usage
Register hooks
class MyClass include Hookable
has_hook :myhook
end
Class level hooks
Connect hook
MyClass.connect_hook(:myhook) do |ret, a, b, c| # a = 1, b = 2, c = 3 puts "Class hook!" ret end
# Call hooks
MyClass.call_hooks(:myhook, args: [1, 2, 3])
Instance level hooks
Create an instance of MyClass
my = MyClass.new
# Connect hook
my.connect_hook(:myhook) do |ret, a, b, c|
# a = 1, b = 2, c = 3
puts "Instance hook!"
ret
end
# Call instance hooks
my.call_instance_hooks_for(:myhook, args: [1, 2, 3])
# Call class hooks
my.call_class_hooks_for(:myhook, args: [1, 2, 3])
# Call both instance and class hooks at once
my.call_hooks_for(:myhook, args: [1, 2, 3])
Class Method Summary collapse
-
.call_for(klass, name, where = nil, args: [], initial: {}) ⇒ Object
Call all blocks that are connected to hook in
klasswithname. -
.connect_hook(klass, name, &block) ⇒ Object
Connect class hook defined in
klasswithnametoblock. -
.connect_instance_hook(klass, name, &block) ⇒ Object
Connect instance hook from instance
klasswithnametoblock. - .hook_classify(klass) ⇒ Object
- .hooks ⇒ Object
-
.register_hook(klass, name, opts = {}) ⇒ Object
Register a hook defined by
klasswithname. - .stop(ret) ⇒ Object
Class Method Details
.call_for(klass, name, where = nil, args: [], initial: {}) ⇒ Object
Call all blocks that are connected to hook in klass with name.
klass may be a class name or an object instance.
If where is set, the blocks are executed in it with instance_exec.
args is an array of arguments given to all blocks. The first argument
to all block is always a return value from previous block or initial,
which defaults to an empty hash.
Blocks are executed one by one in the order they were connected. Blocks must return a hash, that is then passed to the next block and the return value from the last block is returned to the caller.
A block may decide that no further blocks should be executed. In such a case it calls Hooks.stop with the return value. It is then returned to the caller immediately.
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 |
# File 'lib/haveapi/hooks.rb', line 101 def self.call_for(klass, name, where = nil, args: [], initial: {}) classified = hook_classify(klass) catch(:stop) do return initial unless @hooks[classified] hooks = @hooks[classified][name][:listeners] return initial unless hooks hooks.each do |hook| if where ret = where.instance_exec(initial, *args, &hook) else ret = hook.call(initial, *args) end initial.update(ret) if ret end initial end end |
.connect_hook(klass, name, &block) ⇒ Object
Connect class hook defined in klass with name to block.
klass is a class name.
70 71 72 |
# File 'lib/haveapi/hooks.rb', line 70 def self.connect_hook(klass, name, &block) @hooks[hook_classify(klass)][name][:listeners] << block end |
.connect_instance_hook(klass, name, &block) ⇒ Object
Connect instance hook from instance klass with name to block.
75 76 77 78 79 80 81 82 83 84 85 |
# File 'lib/haveapi/hooks.rb', line 75 def self.connect_instance_hook(klass, name, &block) unless @hooks[klass] @hooks[klass] = {} @hooks[klass.class].each do |k, v| @hooks[klass][k] = {listeners: []} end end @hooks[klass][name][:listeners] << block end |
.hook_classify(klass) ⇒ Object
123 124 125 |
# File 'lib/haveapi/hooks.rb', line 123 def self.hook_classify(klass) klass.is_a?(String) ? Object.const_get(klass) : klass end |
.hooks ⇒ Object
64 65 66 |
# File 'lib/haveapi/hooks.rb', line 64 def self.hooks @hooks end |
.register_hook(klass, name, opts = {}) ⇒ Object
Register a hook defined by klass with name.
klass is an instance of Class, that is class name, not it's instance.
opts is a hash and can have following keys:
- desc - why this hook exists, when it's called
- context - the context in which given blocks are called
- args - hash of block arguments
- initial - hash of initial values
- ret - hash of return values
55 56 57 58 59 60 61 62 |
# File 'lib/haveapi/hooks.rb', line 55 def self.register_hook(klass, name, opts = {}) classified = hook_classify(klass) opts[:listeners] = [] @hooks ||= {} @hooks[classified] ||= {} @hooks[classified][name] = opts end |
.stop(ret) ⇒ Object
127 128 129 |
# File 'lib/haveapi/hooks.rb', line 127 def self.stop(ret) throw(ret) end |