module Ably::Modules::EventEmitter
EventEmitter
provides methods to attach to public events and emit events on any class instance
EventEmitter
are typically used for public interfaces, and as such, may be overriden in the classes to enforce ‘event` names match expected values.
@note This module requires that the method logger is defined.
@example
class Example include Modules::EventEmitter end event_emitter = Example.new event_emitter.on(:signal) { |name| puts "Signal #{name} received" } event_emitter.emit :signal, "Test" #=> "Signal Test received"
Public Class Methods
# File lib/submodules/ably-ruby/lib/ably/modules/event_emitter.rb, line 156 def self.included(klass) klass.extend ClassMethods end
Public Instance Methods
Emits an event, calling registered listeners with the given event name and any other given arguments. If an exception is raised in any of the listeners, the exception is caught by the EventEmitter
and the exception is logged to the Ably
logger.
@spec RTE6
# File lib/submodules/ably-ruby/lib/ably/modules/event_emitter.rb, line 90 def emit(event_name, *args) [callbacks_any, callbacks[callbacks_event_coerced(event_name)]].each do |callback_arr| callback_arr.clone. select do |proc_hash| if proc_hash[:unsafe] proc_hash[:emit_proc].call(*args) else safe_yield proc_hash[:emit_proc], *args end end.each do |callback| callback_arr.delete callback end end end
Remove all callbacks for event_name.
If a block is provided, only callbacks matching that block signature will be removed. If block is not provided, all callbacks matching the event_name will be removed.
@spec RTE5
@param [Array<String>] event_names event name
@return [void]
# File lib/submodules/ably-ruby/lib/ably/modules/event_emitter.rb, line 116 def off(*event_names, &block) off_internal(false, *event_names, &block) end
On receiving an event matching the event_name, call the provided block
@spec RTE4
@param [Array<String>] event_names event name
@return [void]
# File lib/submodules/ably-ruby/lib/ably/modules/event_emitter.rb, line 55 def on(*event_names, &block) add_callback event_names, proc_for_block(block) end
On receiving an event maching the event_name, call the provided block only once and remove the registered callback
@spec RTE4
@param [Array<String>] event_names event name
@return [void]
# File lib/submodules/ably-ruby/lib/ably/modules/event_emitter.rb, line 74 def once(*event_names, &block) add_callback event_names, proc_for_block(block, delete_once_run: true) end
Equivalent of {#off} but only unsafe listeners are removed. This method is designed to be used internally by the client library. @api private
# File lib/submodules/ably-ruby/lib/ably/modules/event_emitter.rb, line 123 def unsafe_off(*event_names, &block) off_internal(true, *event_names, &block) end
Equivalent of {#on} but any exception raised in a block will bubble up and cause this client library to fail. This method is designed to be used internally by the client library. @api private
# File lib/submodules/ably-ruby/lib/ably/modules/event_emitter.rb, line 62 def unsafe_on(*event_names, &block) add_callback event_names, proc_for_block(block, unsafe: true) end
Equivalent of {#once} but any exception raised in a block will bubble up and cause this client library to fail. This method is designed to be used internally by the client library. @api private
# File lib/submodules/ably-ruby/lib/ably/modules/event_emitter.rb, line 81 def unsafe_once(*event_names, &block) add_callback event_names, proc_for_block(block, delete_once_run: true, unsafe: true) end
Private Instance Methods
# File lib/submodules/ably-ruby/lib/ably/modules/event_emitter.rb, line 160 def add_callback(event_names, proc_block) if event_names.empty? callbacks_any << proc_block else event_names.each do |event_name| callbacks[callbacks_event_coerced(event_name)] << proc_block end end end
# File lib/submodules/ably-ruby/lib/ably/modules/event_emitter.rb, line 183 def callbacks @callbacks ||= Hash.new { |hash, key| hash[key] = [] } end
# File lib/submodules/ably-ruby/lib/ably/modules/event_emitter.rb, line 187 def callbacks_any @callbacks_any ||= [] end
# File lib/submodules/ably-ruby/lib/ably/modules/event_emitter.rb, line 191 def callbacks_event_coerced(event_name) if self.class.event_emitter_coerce_proc self.class.event_emitter_coerce_proc.call(event_name) else event_name end end
# File lib/submodules/ably-ruby/lib/ably/modules/event_emitter.rb, line 128 def off_internal(unsafe, *event_names, &block) keys = if event_names.empty? callbacks.keys else event_names end if event_names.empty? callbacks_any.delete_if do |proc_hash| if block_given? (proc_hash[:unsafe] == unsafe) && (proc_hash[:block] == block) else proc_hash[:unsafe] == unsafe end end end keys.each do |event_name| callbacks[callbacks_event_coerced(event_name)].delete_if do |proc_hash| if block_given? (proc_hash[:unsafe] == unsafe) && (proc_hash[:block] == block) else proc_hash[:unsafe] == unsafe end end end end
Create a Hash with a proc that calls the provided block and returns true if option :delete_once_run is set to true. emit
automatically deletes any blocks that return true thus allowing a block to be run once
# File lib/submodules/ably-ruby/lib/ably/modules/event_emitter.rb, line 172 def proc_for_block(block, options = {}) { emit_proc: lambda do |*args| block.call(*args) true if options[:delete_once_run] end, block: block, unsafe: options[:unsafe] || false } end