Class: SignalLamp::Lamp

Inherits:
Object
  • Object
show all
Defined in:
lib/signal_lamp/lamp.rb

Overview

A Lamp keeps track of the watchers waiting for events and allows events to be signaled to those watchers. The primary methods used for this are #watch_for() and #signal().

Instance Method Summary collapse

Constructor Details

#initializeLamp

It’s not common to construct these objects directly. Instead, most code should use the SignalLamp::LampHolder mix-in.



14
15
16
# File 'lib/signal_lamp/lamp.rb', line 14

def initialize
  @watchers = { }
end

Instance Method Details

#signal(event_name, *event_details) ⇒ Object

This method will invoke the block code of all previous calls to #watch_for() that are still in effect and that match the passed event_name.

All other arguments passed to this method, assumed to be details related to the event, are passed through to all blocks invoked for this event.



83
84
85
86
87
88
89
# File 'lib/signal_lamp/lamp.rb', line 83

def signal(event_name, *event_details)
  watchers.each_value do |event_matcher, event_handler|
    if event_matcher === event_name
      event_handler.call(event_name, *event_details)
    end
  end
end

#stop_watching(identifier) ⇒ Object

Given an identifier passed to or returned from a previous call to #watch_for(), this method will stop that code from being invoked for any future events.



71
72
73
# File 'lib/signal_lamp/lamp.rb', line 71

def stop_watching(identifier)
  watchers.delete(identifier)
end

#watch_for(event_matcher, identifier: generate_identifier, &event_handler) ⇒ Object

This is the primary interface for watching for events to occur.

The event_matcher parameter will be tested against signaled event names using the === operator. This allows you to match a String directly, use a Regexp to wildcard various event types (I recommend naming events with words separated by colons because these are easy to match), or a Proc that uses any kind of logic to select events. For example, you could match all events signaled on this object with ->(event_name) { true }.

You only need to worry about passing an identifier if you want to later stop watching for the events you will pick up with this call. Alternately you can save the generated identifier returned from this call and later feed that to #stop_watching(). Any Ruby object that can be used as a Hash key is a valid identifier. By default, a UUID String will be generated.

The block passed to this call is the code that will actually be invoked when an event is signaled and the name is matched. The block will be passed the matched event name (useful with dynamic matchers that could select various events) followed by all arguments passed to #signal() for the event.



45
46
47
48
# File 'lib/signal_lamp/lamp.rb', line 45

def watch_for(event_matcher, identifier: generate_identifier, &event_handler)
  watchers[identifier] = [event_matcher, event_handler]
  identifier
end

#watch_for_one(event_matcher, &event_handler) ⇒ Object

This is a shortcut used to create a #watch_for() call that will only trigger for one event. After the block is called the first time, #stop_watching() is automatically called.



55
56
57
58
59
60
61
62
63
64
# File 'lib/signal_lamp/lamp.rb', line 55

def watch_for_one(event_matcher, &event_handler)
  identifier = generate_identifier
  watch_for(event_matcher, identifier: identifier) do |*event_args|
    begin
      event_handler.call(*event_args)
    ensure
      stop_watching(identifier)
    end
  end
end