Module: Statecraft::Machine::ClassMethods
- Defined in:
- lib/statecraft/machine.rb
Overview
Class-level DSL collected declaratively and compiled by finalize!. Names arrive as symbols or strings interchangeably (the ActiveRecord idiom) and are normalized to symbols at the declaration line.
Instance Method Summary collapse
- #compiled_graph ⇒ Object
- #declared_callbacks ⇒ Object
- #declared_edges ⇒ Object
- #declared_event_names ⇒ Object
- #declared_states ⇒ Object
- #event(name, from: nil, to: nil, guard: nil, record_guard: nil, lock: false, &declarations) ⇒ Object
- #events ⇒ Object
-
#finalize! ⇒ Object
Compilation memoizes the graph and freezes the declaration lists, so a reopened machine class fails loudly on any late state/transition/event instead of silently ignoring it (callbacks already freeze in compile).
- #finalized? ⇒ Boolean
- #initial_state ⇒ Object
- #state(name, initial: false) ⇒ Object
- #states ⇒ Object
- #transition(from:, to:, guard: nil, record_guard: nil, lock: false) ⇒ Object
-
#transitions_from(state) ⇒ Object
The graph's shape from one state: a frozen descriptor per outgoing edge,
eventsempty for a bare edge.
Instance Method Details
#compiled_graph ⇒ Object
135 136 137 |
# File 'lib/statecraft/machine.rb', line 135 def compiled_graph finalize! end |
#declared_callbacks ⇒ Object
162 163 164 |
# File 'lib/statecraft/machine.rb', line 162 def declared_callbacks @statecraft_declared_callbacks ||= CALLBACK_PHASES.to_h { |phase| [phase, []] } end |
#declared_edges ⇒ Object
154 155 156 |
# File 'lib/statecraft/machine.rb', line 154 def declared_edges @statecraft_declared_edges ||= [] end |
#declared_event_names ⇒ Object
158 159 160 |
# File 'lib/statecraft/machine.rb', line 158 def declared_event_names @statecraft_declared_event_names ||= [] end |
#declared_states ⇒ Object
150 151 152 |
# File 'lib/statecraft/machine.rb', line 150 def declared_states @statecraft_declared_states ||= [] end |
#event(name, from: nil, to: nil, guard: nil, record_guard: nil, lock: false, &declarations) ⇒ Object
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
# File 'lib/statecraft/machine.rb', line 71 def event(name, from: nil, to: nil, guard: nil, record_guard: nil, lock: false, &declarations) name = name.to_sym declared_event_names << name if declarations if from || to raise CompilationError, "event #{name.inspect} takes either inline from:/to: or a block, not both" end begin @statecraft_current_event = { name: name, lock: lock } yield ensure @statecraft_current_event = nil end else raise CompilationError, "event #{name.inspect} needs from:/to: or a block" if from.nil? || to.nil? @statecraft_current_event = { name: name, lock: false } begin transition(from: from, to: to, guard: guard, record_guard: record_guard, lock: lock) ensure @statecraft_current_event = nil end end end |
#events ⇒ Object
115 116 117 |
# File 'lib/statecraft/machine.rb', line 115 def events compiled_graph.events.keys end |
#finalize! ⇒ Object
Compilation memoizes the graph and freezes the declaration lists, so a reopened machine class fails loudly on any late state/transition/event instead of silently ignoring it (callbacks already freeze in compile).
146 147 148 |
# File 'lib/statecraft/machine.rb', line 146 def finalize! @statecraft_compiled_graph ||= Compiler.new(self).compile.tap { freeze_declarations } end |
#finalized? ⇒ Boolean
139 140 141 |
# File 'lib/statecraft/machine.rb', line 139 def finalized? !@statecraft_compiled_graph.nil? end |
#initial_state ⇒ Object
131 132 133 |
# File 'lib/statecraft/machine.rb', line 131 def initial_state compiled_graph.initial_state end |
#state(name, initial: false) ⇒ Object
58 59 60 |
# File 'lib/statecraft/machine.rb', line 58 def state(name, initial: false) declared_states << { name: name.to_sym, initial: initial } end |
#states ⇒ Object
111 112 113 |
# File 'lib/statecraft/machine.rb', line 111 def states compiled_graph.states end |
#transition(from:, to:, guard: nil, record_guard: nil, lock: false) ⇒ Object
62 63 64 65 66 67 68 69 |
# File 'lib/statecraft/machine.rb', line 62 def transition(from:, to:, guard: nil, record_guard: nil, lock: false) declared_edges << { from: from.to_sym, to: to.to_sym, guards: Array(guard), record_guards: Array(record_guard), lock: lock || current_event_lock, event: current_event_name } end |
#transitions_from(state) ⇒ Object
The graph's shape from one state: a frozen descriptor per outgoing
edge, events empty for a bare edge. Shape, not a prediction — no
guards are consulted, and a state outside the graph honestly owns no
edges. Class-level on purpose: the answer is a property of the graph,
never of a record.
124 125 126 127 128 129 |
# File 'lib/statecraft/machine.rb', line 124 def transitions_from(state) normalized = state.to_sym compiled_graph.edges.filter_map do |(from, _to), edge| { to: edge.to, events: edge.event_names }.freeze if from == normalized end.freeze end |