Class: DuoRuby::Channel
- Inherits:
-
Object
- Object
- DuoRuby::Channel
- Extended by:
- HandlerMethods
- Defined in:
- lib/duoruby/channel.rb,
lib/duoruby/channel/namespace.rb,
lib/duoruby/channel/handler_methods.rb
Overview
Base class for event-driven components in DuoRuby.
Channel provides a flexible pub/sub event system with support for:
-
Class-level handler declarations that are inherited by subclasses
-
Module-level handler declarations that merge into including classes
-
Per-instance handler isolation (class handlers are deep-cloned on initialize)
-
One-shot handlers via #one
-
Wildcard handlers that run on every event via #on with the * event name
-
Removal by event name, proc reference, or Handler token
Defined Under Namespace
Modules: HandlerMethods Classes: Handler, Namespace
Instance Attribute Summary collapse
-
#handlers ⇒ Hash{String => Array<Handler>}
readonly
The event-to-handlers map for this object.
Class Method Summary collapse
-
.inherited(subclass) ⇒ Object
Copies the parent class’s handlers into the subclass when a subclass is defined.
Instance Method Summary collapse
- #channel(name) ⇒ Object
-
#dispatch(event, *args, **params) ⇒ nil
(also: #trigger)
Dispatches
eventto all registered handlers, then to any wildcard (+*+) handlers. -
#handler_for(event) ⇒ Proc?
Returns a Proc wrapping the first registered handler for
event, bound to this instance viainstance_exec. - #initialize ⇒ Channel constructor
-
#off(event = nil, handler = nil, &block) ⇒ Object
Removes instance-level handlers.
-
#on(event, &handler) ⇒ Handler
Registers a persistent instance-level handler for
event. -
#one(event, &handler) ⇒ Handler
Registers a one-shot instance-level handler for
event.
Methods included from HandlerMethods
Constructor Details
Instance Attribute Details
#handlers ⇒ Hash{String => Array<Handler>} (readonly)
Returns the event-to-handlers map for this object.
30 31 32 |
# File 'lib/duoruby/channel.rb', line 30 def handlers @handlers end |
Class Method Details
.inherited(subclass) ⇒ Object
Copies the parent class’s handlers into the subclass when a subclass is defined.
41 42 43 44 |
# File 'lib/duoruby/channel.rb', line 41 def self.inherited(subclass) subclass.__send__(:merge_handlers, handlers) super end |
Instance Method Details
#channel(name) ⇒ Object
98 99 100 |
# File 'lib/duoruby/channel.rb', line 98 def channel(name) Namespace.new(self, name) end |
#dispatch(event, *args, **params) ⇒ nil Also known as: trigger
Dispatches event to all registered handlers, then to any wildcard (+*+) handlers.
All handlers are invoked via instance_exec so they run in the context of this Channel instance. Positional args and keyword params are forwarded as-is. One-shot handlers are removed immediately after firing.
124 125 126 127 128 129 |
# File 'lib/duoruby/channel.rb', line 124 def dispatch(event, *args, **params) event = event.to_s results = dispatch_handlers(event, handlers[event], *args, **params) dispatch_handlers("*", handlers["*"], event, *args, **params) results end |
#handler_for(event) ⇒ Proc?
Returns a Proc wrapping the first registered handler for event, bound to this instance via instance_exec. Returns nil if no handler exists. Used internally; may be useful for adapter integrations.
108 109 110 111 112 |
# File 'lib/duoruby/channel.rb', line 108 def handler_for(event) event = event.to_s handler = handlers[event]&.first proc { |*args, **params| instance_exec(*args, **params, &handler.block) } if handler end |
#off(event = nil, handler = nil, &block) ⇒ Object
Removes instance-level handlers. See DuoRuby::Channel::HandlerMethods#off for the full removal semantics — behaviour is identical at the instance level.
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
# File 'lib/duoruby/channel.rb', line 81 def off(event = nil, handler = nil, &block) target = handler || block return handlers.clear unless event if event.is_a?(Handler) handlers[event.event]&.delete_if { |r| handler_identity?(r, event) } handlers.delete(event.event) if handlers[event.event]&.empty? return end event = event.to_s return handlers.delete(event) unless target handlers[event]&.delete_if { |r| handler_identity?(r, target) } handlers.delete(event) if handlers[event]&.empty? end |
#on(event, &handler) ⇒ Handler
Registers a persistent instance-level handler for event. Instance handlers stack on top of any class-level handlers that were copied in at initialize time.
58 59 60 61 62 63 64 |
# File 'lib/duoruby/channel.rb', line 58 def on(event, &handler) raise ArgumentError, "handler required" unless handler event = event.to_s handlers[event] ||= [] Handler.new(event, handler, false).tap { |registered| handlers[event] << registered } end |
#one(event, &handler) ⇒ Handler
Registers a one-shot instance-level handler for event. Automatically removed after the first dispatch.
71 72 73 74 75 76 77 |
# File 'lib/duoruby/channel.rb', line 71 def one(event, &handler) raise ArgumentError, "handler required" unless handler event = event.to_s handlers[event] ||= [] Handler.new(event, handler, true).tap { |registered| handlers[event] << registered } end |