Class: FiniteMachine::Observer
- Inherits:
-
GenericDSL
- Object
- GenericDSL
- FiniteMachine::Observer
- Includes:
- Safety
- Defined in:
- lib/roseflow/finite_machine.rb
Overview
A class responsible for observing state changes
Defined Under Namespace
Instance Attribute Summary collapse
-
#hooks ⇒ Object
readonly
The hooks to trigger around the transition lifecycle.
-
#machine ⇒ Object
readonly
The current state machine.
Instance Method Summary collapse
-
#call(&block) ⇒ Object
private
Evaluate in current context.
- #callback_queue ⇒ Object
-
#cancel_event(msg = nil) ⇒ Object
Cancel the current event.
-
#cleanup_callback_queue(_id) ⇒ Object
private
Clean up callback queue.
-
#emit(event, *data) ⇒ nil
Execute each of the hooks in order with supplied data.
-
#initialize(machine) ⇒ Observer
constructor
Initialize an Observer.
-
#off(hook_type, name = ANY_STATE, &callback) ⇒ Object
Unregister callback for a given event.
-
#on(hook_type, state_or_event_name = nil, async = nil, &callback) ⇒ Object
Register callback for a given hook type.
- #on_after(*args, &callback) ⇒ Object
- #on_before(*args, &callback) ⇒ Object
- #on_enter(*args, &callback) ⇒ Object
- #on_exit(*args, &callback) ⇒ Object
- #on_transition(*args, &callback) ⇒ Object
- #once_on_after(*args, &callback) ⇒ Object
- #once_on_before(*args, &callback) ⇒ Object
- #once_on_enter(*args, &callback) ⇒ Object
- #once_on_exit(*args, &callback) ⇒ Object
- #once_on_transition(*args, &callback) ⇒ Object
Constructor Details
#initialize(machine) ⇒ Observer
Initialize an Observer
37 38 39 40 41 42 43 44 |
# File 'lib/roseflow/finite_machine.rb', line 37 def initialize(machine) @id = ULID.generate @machine = machine @hooks = Hooks.new @machine.subscribe(self) ObjectSpace.define_finalizer(@id, method(:cleanup_callback_queue)) end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(method_name, *args, &block) ⇒ self (private)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Forward the message to observer
232 233 234 235 236 237 238 239 |
# File 'lib/roseflow/finite_machine.rb', line 232 def method_missing(method_name, *args, &block) _, event_name, callback_name = *method_name.to_s.match(/^(\w*?on_\w+?)_(\w+)$/) if callback_name && callback_names.include?(callback_name.to_sym) public_send(event_name, :"#{callback_name}", *args, &block) else super end end |
Instance Attribute Details
#hooks ⇒ Object (readonly)
The hooks to trigger around the transition lifecycle.
29 30 31 |
# File 'lib/roseflow/finite_machine.rb', line 29 def hooks @hooks end |
#machine ⇒ Object (readonly)
The current state machine
26 27 28 |
# File 'lib/roseflow/finite_machine.rb', line 26 def machine @machine end |
Instance Method Details
#call(&block) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Evaluate in current context
53 54 55 |
# File 'lib/roseflow/finite_machine.rb', line 53 def call(&block) instance_eval(&block) end |
#callback_queue ⇒ Object
46 47 48 |
# File 'lib/roseflow/finite_machine.rb', line 46 def callback_queue @callback_queue ||= MessageQueue.new end |
#cancel_event(msg = nil) ⇒ Object
Cancel the current event
This should be called inside a on_before or on_exit callbacks to prevent event transition.
165 166 167 |
# File 'lib/roseflow/finite_machine.rb', line 165 def cancel_event(msg = nil) raise CallbackError.new(msg) end |
#cleanup_callback_queue(_id) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Clean up callback queue
18 19 20 21 22 23 |
# File 'lib/roseflow/finite_machine.rb', line 18 def cleanup_callback_queue(_id) if callback_queue.alive? callback_queue.shutdown end rescue MessageQueueDeadError end |
#emit(event, *data) ⇒ nil
Execute each of the hooks in order with supplied data
142 143 144 145 146 147 148 149 150 151 152 153 154 |
# File 'lib/roseflow/finite_machine.rb', line 142 def emit(event, *data) sync_exclusive do [event.type].each do |hook_type| any_state_or_event = HookEvent.any_state_or_event(hook_type) [any_state_or_event, event.name].each do |event_name| hooks[hook_type][event_name].each do |hook| handle_callback(hook, event, *data) off(hook_type, event_name, &hook) if hook.is_a?(Once) end end end end end |
#off(hook_type, name = ANY_STATE, &callback) ⇒ Object
Unregister callback for a given event
82 83 84 85 86 |
# File 'lib/roseflow/finite_machine.rb', line 82 def off(hook_type, name = ANY_STATE, &callback) sync_exclusive do hooks.unregister hook_type, name, callback end end |
#on(hook_type, state_or_event_name = nil, async = nil, &callback) ⇒ Object
Register callback for a given hook type
67 68 69 70 71 72 73 74 75 76 77 |
# File 'lib/roseflow/finite_machine.rb', line 67 def on(hook_type, state_or_event_name = nil, async = nil, &callback) sync_exclusive do if state_or_event_name.nil? state_or_event_name = HookEvent.any_state_or_event(hook_type) end async = false if async.nil? ensure_valid_callback_name!(hook_type, state_or_event_name) callback.extend(Async) if async == :async hooks.register(hook_type, state_or_event_name, callback) end end |
#on_after(*args, &callback) ⇒ Object
120 121 122 |
# File 'lib/roseflow/finite_machine.rb', line 120 def on_after(*args, &callback) on HookEvent::After, *args, &callback end |
#on_before(*args, &callback) ⇒ Object
116 117 118 |
# File 'lib/roseflow/finite_machine.rb', line 116 def on_before(*args, &callback) on HookEvent::Before, *args, &callback end |
#on_enter(*args, &callback) ⇒ Object
92 93 94 |
# File 'lib/roseflow/finite_machine.rb', line 92 def on_enter(*args, &callback) on HookEvent::Enter, *args, &callback end |
#on_exit(*args, &callback) ⇒ Object
100 101 102 |
# File 'lib/roseflow/finite_machine.rb', line 100 def on_exit(*args, &callback) on HookEvent::Exit, *args, &callback end |
#on_transition(*args, &callback) ⇒ Object
96 97 98 |
# File 'lib/roseflow/finite_machine.rb', line 96 def on_transition(*args, &callback) on HookEvent::Transition, *args, &callback end |
#once_on_after(*args, &callback) ⇒ Object
128 129 130 |
# File 'lib/roseflow/finite_machine.rb', line 128 def once_on_after(*args, &callback) on HookEvent::After, *args, &callback.extend(Once) end |
#once_on_before(*args, &callback) ⇒ Object
124 125 126 |
# File 'lib/roseflow/finite_machine.rb', line 124 def once_on_before(*args, &callback) on HookEvent::Before, *args, &callback.extend(Once) end |
#once_on_enter(*args, &callback) ⇒ Object
104 105 106 |
# File 'lib/roseflow/finite_machine.rb', line 104 def once_on_enter(*args, &callback) on HookEvent::Enter, *args, &callback.extend(Once) end |
#once_on_exit(*args, &callback) ⇒ Object
112 113 114 |
# File 'lib/roseflow/finite_machine.rb', line 112 def once_on_exit(*args, &callback) on HookEvent::Exit, *args, &callback.extend(Once) end |
#once_on_transition(*args, &callback) ⇒ Object
108 109 110 |
# File 'lib/roseflow/finite_machine.rb', line 108 def once_on_transition(*args, &callback) on HookEvent::Transition, *args, &callback.extend(Once) end |