Module: Volt::Eventable

Included in:
Channel, ChannelStub, ComponentNode, MessageBus::PeerToPeer, ReactiveArray, ServerSetup::App
Defined in:
lib/volt/reactive/eventable.rb

Overview

Include Eventable to add a basic event/trigger system to a class. Listeners can be added with #on(event_name) { … } Events can be triggered with #trigger!

Instance Method Summary collapse

Instance Method Details

#on(*events, &callback) ⇒ Object

Sets up a listener on the class the Eventable module was included in. event should be a string or symbol. When something calls #trigger!(event_name) on the class, it will trigger any listener with the same event name.

returns: a listener that has a #remove method to stop the listener.



47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/volt/reactive/eventable.rb', line 47

def on(*events, &callback)
  fail '.on requires an event' if events.size == 0

  listener = Listener.new(self, events, callback)

  @listeners ||= {}

  events.each do |event|
    event             = event.to_sym
    @listeners[event] ||= []
    @listeners[event] << listener

    first_for_event = @listeners[event].size == 1
    first           = first_for_event && @listeners.size == 1

    # Let the included class know that an event was registered. (if it cares)
    if self.respond_to?(:event_added)
      # call event added passing the event, the scope, and a boolean if it
      # is the first time this event has been added.
      event_added(event, first, first_for_event)
    end
  end

  listener
end

#remove_listener(event, listener) ⇒ Object

Stops the listener returned by calling .on(:event_name) Triggers #event_removed if there are no more listeners for that event.



89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/volt/reactive/eventable.rb', line 89

def remove_listener(event, listener)
  event = event.to_sym

  fail "Unable to delete #{event} from #{inspect}" unless @listeners && @listeners[event]

  @listeners[event].delete(listener)

  last_for_event = @listeners[event].size == 0

  if last_for_event
    # No registered listeners now on this event
    @listeners.delete(event)
  end

  last = last_for_event && @listeners.size == 0

  # Let the class we're included on know that we removed a listener (if it cares)
  if self.respond_to?(:event_removed)
    # Pass in the event and a boolean indicating if it is the last event
    event_removed(event, last, last_for_event)
  end
end

#trigger!(event, *args) ⇒ Object

Triggers event on the class the module was includeded. Any .on listeners will have their block called passing in *args.



75
76
77
78
79
80
81
82
83
84
85
# File 'lib/volt/reactive/eventable.rb', line 75

def trigger!(event, *args)
  event = event.to_sym

  if @listeners && @listeners[event]
    # TODO: We have to dup here because one trigger might remove another
    @listeners[event].dup.each do |listener|
      # Call the event on each listener
      listener.call(*args)
    end
  end
end