Module: Fidgit::Event

Included in:
Element
Defined in:
lib/fidgit/event.rb

Overview

Adds simple event handling methods to an object (subscribe/publish pattern).

Examples:

class JumpingBean
  include Event
  event :jump
end

bean = JumpingBean.new
bean.subscribe :jump do
  puts "Whee!"
end

bean.subscribe :jump do |object, direction, distance|
  puts "#{object.class.name} jumped #{distance} metres #{direction}"
end

bean.publish :jump, :up, 4
# Whee!
# JumpingBean jumped 4 metres up

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.included(base) ⇒ Object

Add singleton methods to the class that includes Event.



77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/fidgit/event.rb', line 77

def self.included(base)
  class << base
    def events
      # Copy the events already set up for your parent.

      unless defined? @events
        @events = if superclass.respond_to? :events
          superclass.events.dup
        else
          []
        end
      end

      @events
    end

    def event(event)
      events.push event.to_sym unless events.include? event
      event
    end
  end
end

Instance Method Details

#eventsObject

The list of events that this object can publish/subscribe.



72
73
74
# File 'lib/fidgit/event.rb', line 72

def events
  self.class.events
end

#publish(event, *args) ⇒ Symbol?

Publish an event to all previously added handlers in the order they were added. It will automatically call the publishing object with the method named after the event if it is defined (this will be done before the manually added handlers are called).

If any handler returns :handled, then no further handlers will be called.

Parameters:

  • event (Symbol)

    Name of the event to publish.

  • args (Array)

    Arguments to pass to the event handlers.

Returns:

  • (Symbol, nil)

    :handled if any handler handled the event or nil if none did.

Raises:

  • (ArgumentError)


52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/fidgit/event.rb', line 52

def publish(event, *args)
  raise ArgumentError, "#{self.class} does not handle #{event.inspect}" unless events.include? event

  # Do nothing if the object is disabled.

  return if respond_to?(:enabled?) and not enabled?

  if respond_to? event
    return :handled if send(event, self, *args) == :handled
  end

  if defined? @_event_handlers
    @_event_handlers[event].reverse_each do |handler|
      return :handled if handler.call(self, *args) == :handled
    end
  end

  nil
end

#subscribe(event, method) ⇒ nil #subscribe(event, &block) ⇒ nil

Overloads:

  • #subscribe(event, method) ⇒ nil

    Add an event handler for an event, using a method.

    Returns:

    • (nil)
  • #subscribe(event, &block) ⇒ nil

    Add an event handler for an event, using a block.

    Returns:

    • (nil)

Raises:

  • (ArgumentError)


33
34
35
36
37
38
39
40
41
# File 'lib/fidgit/event.rb', line 33

def subscribe(event, method = nil, &block)
  raise ArgumentError, "Expected method or block for event handler" unless !block.nil? ^ !method.nil?
  raise ArgumentError, "#{self.class} does not handle #{event.inspect}" unless events.include? event

  @_event_handlers ||= Hash.new() { |hash, key| hash[key] = [] }
  @_event_handlers[event].push(method ? method : block)

  nil
end