Class: Brainguy::Emitter

Inherits:
Set
  • Object
show all
Defined in:
lib/brainguy/emitter.rb,
lib/brainguy/subscription_scope.rb

Overview

This object keeps track of all the listeners (observers) subscribed to a particular event source object.

Constant Summary collapse

DEFAULT_NOTIFIER =
BasicNotifier.new

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(event_source = self, options = {}) ⇒ Emitter

Returns a new instance of Emitter.

Parameters:

  • event_source (Object) (defaults to: self)

    the event-originating object

  • options (Hash) (defaults to: {})

    a customizable set of options

Options Hash (options):

  • :subscriptions (Set<Subscription>) — default: Set.new

    the underlying set of subscriptions

  • :notifier_maker (:call)

    a factory for notifiers.



32
33
34
35
36
37
38
# File 'lib/brainguy/emitter.rb', line 32

def initialize(event_source = self, options = {})
  super(options[:subscriptions] || Set.new)
  @event_source   = event_source
  @notifier_maker = options.fetch(:notifier_maker) {
    ->() { DEFAULT_NOTIFIER }
  }
end

Class Method Details

.new_from_existing(event_source, subscription_set) ⇒ Emitter

Create a new Brainguy::Emitter that shares its inner dataset with an existing one. This exists so that it's possible to generate temporary copies of a Brainguy::Emitter with different, specialized semantics; for instance, an IdempotentEmitter that shares the same set of subscriptions as an existing Brainguy::Emitter.

Parameters:

  • event_source (Object)

    the event-originating object

  • subscription_set (Emitter)

    the existing set to share subscriptions with

Returns:



24
25
26
# File 'lib/brainguy/emitter.rb', line 24

def self.new_from_existing(event_source, subscription_set)
  new(event_source, subscriptions: subscription_set.subscriptions)
end

Instance Method Details

#attach(new_listener) ⇒ Subscription

Attach a new object to listen for events. A listener is expected to be call-able, and it will receive the #call message with an Brainguy::Event each time one is emitted.

Parameters:

  • new_listener (:call)

Returns:

  • (Subscription)

    a subscription object which can be used to cancel the subscription.



51
52
53
54
55
# File 'lib/brainguy/emitter.rb', line 51

def attach(new_listener)
  FullSubscription.new(self, new_listener).tap do |subscription|
    self << subscription
  end
end

#detach(listener) ⇒ void

This method returns an undefined value.

Detach a listener. This locates the subscription corresponding to the given listener (if any), and removes it.

Parameters:

  • listener (:call)

    a listener to be unsubscribed



61
62
63
# File 'lib/brainguy/emitter.rb', line 61

def detach(listener)
  delete(FullSubscription.new(self, listener))
end

#emit(event_name, *extra_args) ⇒ Object

Emit an event to be distributed to all interested listeners.

Parameters:

  • event_name (Symbol)

    the name of the event

  • extra_args (Array)

    any extra arguments that should accompany the event

Returns:

  • the notifier's result value



92
93
94
95
96
97
98
99
# File 'lib/brainguy/emitter.rb', line 92

def emit(event_name, *extra_args)
  notifier = @notifier_maker.call
  each do |subscription|
    event = Event.new(event_name, @event_source, extra_args)
    notifier.notify(subscription, event)
  end
  notifier.result
end

#on(name, &block) ⇒ Subscription #on(handlers) ⇒ Subscription

Attach blocks of code to handle specific named events.

Overloads:

  • #on(name, &block) ⇒ Subscription

    Attach a block to be called for a specific event. The block will be called with the event arguments (not the event object).

    Parameters:

    • name (Symbol)
    • block (Proc)

      what to do when the event is emitted

  • #on(handlers) ⇒ Subscription

    Attach multiple event-specific handlers at once.

    Parameters:

    • handlers (Hash{Symbol => [:call]})

      a map of event names to callable handlers.

Returns:

  • (Subscription)

    a subscription object which can be used to cancel the subscription.



76
77
78
79
80
81
82
83
84
85
# File 'lib/brainguy/emitter.rb', line 76

def on(name_or_handlers, &block)
  case name_or_handlers
  when Symbol
    attach_to_single_event(name_or_handlers, block)
  when Hash
    attach(OpenObserver.new(name_or_handlers))
  else
    fail ArgumentError, "Event name or Hash required"
  end
end

#subscriptionsSet<Subscription>

Returns the underlying set of subscription objects.

Returns:

  • (Set<Subscription>)

    the underlying set of subscription objects



41
42
43
# File 'lib/brainguy/emitter.rb', line 41

def subscriptions
  __getobj__
end

#with_subscription_scope {|SubscriptionScope| ... } ⇒ Object

Yields:



58
59
60
# File 'lib/brainguy/subscription_scope.rb', line 58

def with_subscription_scope(&block)
  SubscriptionScope.open(self, &block)
end