summaryrefslogtreecommitdiffstats
path: root/test/lib/spec/callback/callback_container.rb
blob: 24d4c0cedfb7839629bd6c4b99a8963b223e07c5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
module Callback
  class CallbackContainer
    def initialize
      @callback_registry = Hash.new do |hash, key|
        hash[key] = Array.new
      end
    end

    # Defines the callback with the key in this container.
    def define(key, callback_proc=nil, &callback_block)
      callback = extract_callback(callback_block, callback_proc) do
        raise "You must define the callback that accepts the call method."
      end
      @callback_registry[key] << callback
      callback
    end

    # Undefines the callback with the key in this container.
    def undefine(key, callback_proc)
      callback = extract_callback(callback_proc) do
        raise "You may only undefine callbacks that use the call method."
      end
      @callback_registry[key].delete callback
      callback
    end

    # Notifies the callbacks for the key. Arguments may be passed.
    # An error handler may be passed in as a block. If there is an error, the block is called with
    # error object as an argument.
    # An array of the return values of the callbacks is returned.
    def notify(key, *args, &error_handler)
      @callback_registry[key].collect do |callback|
        begin
          callback.call(*args)
        rescue Exception => e
          yield(e) if error_handler
        end
      end
    end

    # Clears all of the callbacks in this container.
    def clear
      @callback_registry.clear
    end

    protected
    def extract_callback(first_choice_callback, second_choice_callback = nil)
      callback = nil
      if first_choice_callback
        callback = first_choice_callback
      elsif second_choice_callback
        callback = second_choice_callback
      end
      unless callback.respond_to? :call
        yield
      end
      return callback
    end
  end
end