Documentation
¶
Overview ¶
Package aasm is a pure-Go (CGO-free) reimplementation of the deterministic core of Ruby's aasm gem — "Acts As State Machine". It reproduces the state machine DEFINITION (states with initial/final flags and enter/exit callbacks; events with from→to transitions, guards, and before/after/success/error/ after_commit callbacks) and the runtime that fires an event against a host object — the current state, the may_fire?/fire/fire! trio, permitted events, whiny transitions, and the faithful AASM callback ordering — without any Ruby runtime.
It is the AASM engine for [go-embedded-ruby](https://github.com/go-embedded-ruby/ruby), but a standalone, reusable module.
Definition and instance ¶
A Machine is a state-machine definition, built with a small fluent DSL that mirrors the gem's `aasm do … end` block:
m := aasm.New("").
State("sleeping", aasm.Initial()).
State("running").
Event("run", aasm.Transitions(aasm.Transition{
From: []string{"sleeping"}, To: "running",
}))
A Machine carries no per-object state. It is bound to a host object through Seams to yield an Instance:
inst := m.Bind(aasm.Seams{
GetState: func() string { return obj.state },
SetState: func(s string) error { obj.state = s; return nil },
Persist: func() error { return db.Save(obj) },
})
inst.CurrentState() // "sleeping" (the initial state until set)
ok, err := inst.MayFire("run")
ok, err = inst.Fire("run") // in-memory transition
ok, err = inst.FireBang("run") // transition + Persist (the gem's `run!`)
Seams ¶
The three host couplings are seams so the same engine drives a plain struct, an ORM row, or a Ruby object:
- GetState / SetState read and write the current state on the host object (the gem's aasm_read_state / aasm_write_state).
- Persist is invoked by FireBang only, after the in-memory transition, to persist the object (the gem's `event!` save). Fire never persists.
Guards and callbacks are themselves seams — Guard is func([]any) (bool, error) and Callback is func([]any) (any, error) — that a binding wires to Ruby methods or blocks; the `any` return mirrors a Ruby method result and is ignored by the engine.
Callback ordering ¶
A successful fire runs, in order: the transition guards (to select the transition), the event `before`, the transition `before`, the old state's `exit`, the state change, the new state's `enter`, the transition `after`, the event `after`, then — for FireBang — Persist, then the transition and event `success`, and finally — for FireBang — `after_commit`. Any callback error stops the sequence and is routed to the event's `error` callbacks (which may swallow or re-raise); if none are defined it propagates. A guard that returns false is not an error: it blocks the transition, which raises ErrInvalidTransition when whiny (the default) or returns (false, nil) when Machine.WhinyTransitions is false.
Index ¶
- Variables
- type Callback
- type ErrorCallback
- type EventOption
- type Guard
- type Instance
- func (i *Instance) CurrentState() string
- func (i *Instance) Events() []string
- func (i *Instance) Fire(name string, args ...any) (bool, error)
- func (i *Instance) FireBang(name string, args ...any) (bool, error)
- func (i *Instance) Is(state string) bool
- func (i *Instance) Machine() *Machine
- func (i *Instance) MayFire(name string, args ...any) (bool, error)
- func (i *Instance) PermittedEvents(args ...any) []string
- func (i *Instance) States() []string
- type Machine
- func (m *Machine) Bind(s Seams) *Instance
- func (m *Machine) Event(name string, opts ...EventOption) *Machine
- func (m *Machine) Events() []string
- func (m *Machine) InitialState() string
- func (m *Machine) Name() string
- func (m *Machine) State(name string, opts ...StateOption) *Machine
- func (m *Machine) States() []string
- func (m *Machine) WhinyTransitions(v bool) *Machine
- type Seams
- type StateOption
- type Transition
Constants ¶
This section is empty.
Variables ¶
var ( // ErrUndefinedEvent is returned (when whiny) by Fire / FireBang for an event // the machine does not define — the gem raises AASM::UndefinedState / // NoMethodError for `obj.no_such_event!`. ErrUndefinedEvent = errors.New("aasm: undefined event") // ErrInvalidTransition is returned (when whiny) when the event is defined but // no transition is available from the current state — either no transition // lists the state in its `from` set, or every candidate's guards blocked it. // It mirrors the gem's AASM::InvalidTransition. ErrInvalidTransition = errors.New("aasm: invalid transition") )
The gem's transition errors, exposed as sentinels so a host (rbgo) can map them onto the Ruby AASM exception tree and callers can match with errors.Is.
Functions ¶
This section is empty.
Types ¶
type Callback ¶
Callback is a state/event callback seam. It receives the arguments passed to Fire/FireBang and returns a value (mirroring a Ruby method result, ignored by the engine) and an error. A non-nil error stops the transition.
type ErrorCallback ¶
ErrorCallback is the event `error` seam. It receives the error raised during a transition and may return nil to swallow it or an error to propagate.
type EventOption ¶
type EventOption func(*eventDef)
EventOption configures an event in Machine.Event.
func AfterCommit ¶
func AfterCommit(cb Callback) EventOption
AfterCommit appends an event-level after_commit callback, run by FireBang only after Persist and the success callbacks.
func Success ¶
func Success(cb Callback) EventOption
Success appends an event-level success callback (run after the transition and, for FireBang, after Persist).
func Transitions ¶
func Transitions(t Transition) EventOption
Transitions appends a transition to the event (the gem's `transitions from:, to:, guard:, …` inside an `event` block).
type Guard ¶
Guard is a transition guard seam: it decides whether a transition may be taken. A false result blocks the transition (not an error); a non-nil error aborts the fire and is routed to the event's error callbacks.
type Instance ¶
type Instance struct {
// contains filtered or unexported fields
}
Instance is a Machine bound to a host object through Seams.
func (*Instance) CurrentState ¶
CurrentState reports the host's current state, defaulting to the machine's initial state while the host state is blank (the gem's `aasm.current_state`).
func (*Instance) Fire ¶
Fire runs the event as an in-memory transition (no Persist), returning whether it transitioned. See the package doc for callback ordering.
func (*Instance) FireBang ¶
FireBang runs the event and, on success, invokes Persist (the gem's `event!`).
func (*Instance) MayFire ¶
MayFire reports whether event could fire from the current state — the event is defined and some transition's from set matches with guards passing (the gem's `may_event?`). A guard error is surfaced.
func (*Instance) PermittedEvents ¶
PermittedEvents returns the names of events that may fire from the current state, in declaration order (the gem's `aasm.permitted_events`). An event whose guard evaluation errors is treated as not permitted.
type Machine ¶
type Machine struct {
// contains filtered or unexported fields
}
Machine is a state-machine definition — the pure-Go analogue of one `aasm do … end` block. It holds states and events but no per-object state; bind it to a host with Machine.Bind. A class with several `aasm(:name) do … end` blocks maps to several independent Machines.
func New ¶
New returns an empty machine with the given name (use "" for the gem's default unnamed machine). Whiny transitions are on by default, matching the gem.
func (*Machine) Event ¶
func (m *Machine) Event(name string, opts ...EventOption) *Machine
Event declares (or extends) an event and returns the machine for chaining. States named by the event's transitions are auto-registered if not already declared.
func (*Machine) InitialState ¶
InitialState reports the state name flagged initial, or "" if none is.
func (*Machine) State ¶
func (m *Machine) State(name string, opts ...StateOption) *Machine
State declares (or extends) a state and returns the machine for chaining.
func (*Machine) WhinyTransitions ¶
WhinyTransitions toggles whether a blocked/invalid Fire returns an error (true, the default) or (false, nil). It returns the machine for chaining.
type Seams ¶
Seams couple a Machine to a host object. GetState/SetState read and write the current state (the gem's aasm_read_state / aasm_write_state); Persist, optional, is invoked by FireBang only, after the in-memory transition.
type StateOption ¶
type StateOption func(*stateDef)
StateOption configures a state in Machine.State.
func Enter ¶
func Enter(cb Callback) StateOption
Enter appends an enter callback, run when the machine enters the state.
func Exit ¶
func Exit(cb Callback) StateOption
Exit appends an exit callback, run when the machine leaves the state.
func Final ¶
func Final() StateOption
Final flags the state as a final state (the gem's `state :x, final: true`).
func Initial ¶
func Initial() StateOption
Initial flags the state as the machine's initial state (the gem's `state :x, initial: true`).
type Transition ¶
type Transition struct {
From []string
To string
Guards []Guard
Unless []Guard
Before []Callback
After []Callback
Success []Callback
}
Transition is the specification of one from→to transition passed to Transitions. Guards must all pass and Unless guards must all fail for the transition to be selected.
