Skip to content

veelenga/aasm.cr

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

20 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

aasm.cr Build Status

Aasm stands for "Acts As State Machine" which means that some abstract object can act as a finite state machine and can be in one of a finite number of states at a time; can change one state to another when initiated by a triggering event.

Getting Started

Adding a state machine to a Crystal class is as simple as including AASM module and writing act_as_state_machine method where you can define states and events with their transitions:

class Transaction
  include AASM

  def act_as_state_machine
    aasm.state :pending, initial: true
    aasm.state :active,  enter: -> { puts "Just got activated" }
    aasm.state :completed

    aasm.event :activate do |e|
      e.transitions from: :pending, to: :active
    end

    aasm.event :complete do |e|
      e.transitions from: :active, to: :completed
    end
  end
end

t = Transaction.new.tap &.act_as_state_machine
t.state          #=> :pending
t.next_state     #=> :active
t.fire :activate # Just got activated
t.state          #=> :active
t.next_state     #=> :completed

States

State can be defined using aasm.state method passing the name and options:

aasm.state :passive, initial: true

State options

Currently state supports the following options:

  • initial : Bool optional - indicates whether this state is initial or not. If initial state not specified, first one will be considered as initial
  • guard : (-> Bool) optional - a callback, that gets evaluated once state is getting entered. State will not enter if guard returns false
  • enter : (->) optional - a hook, that gets evaluated once state entered.

Events

Event can be defined using aasm.state method passing the name and a block with transitions:

aasm.event :delete do |e|
  e.transitions from: :active, to: :deleted
end

Event has to be defined after state definition. In other case NoSuchStateException will be raise.

Event options

Currently event supports the following options:

  • before : (->) optional - a callback, that gets evaluated once before changing a state
  • after : (->) optional - a callback, that gets evaluated once after changing a state.

Transitions

Transition can be defined on event with transitions method passing options:

aasm.event :complete do |e|
  e.transitions from: [:pending, :active], to: :deleted
end

Transition options

Currently transition supports the following options:

  • from : (Symbol | Array(Symbol)) required - state (or states) from which state of state machine can be changed when event fired
  • to : Symbol required - state to which state of state machine will change when event fired.

More examples

One state machine (circular)

class CircularStateMachine
  include AASM

  def act_as_state_machine
    aasm.state :started

    aasm.event :restart do |e|
      e.transitions from: :started, to: :started
    end
  end
end

Two states machine

class TwoStateMachine
  include AASM

  def act_as_state_machine
    assm.state :active
    aasm.state :deleted

    aasm.event :delete do |e|
      e.transitions from: :active, to: :deleted
    end
  end
end

Three states machine

class ThreeStatesMachine
  include AASM

  def act_as_state_machine
    aasm.state :pending, initial: true
    aasm.state :active
    aasm.state :completed

    aasm.event :activate do |e|
      e.transitions from: :pending, to: :active
    end
    aasm.event :complete do |e|
      e.before { puts "completing..." }
      e.after  { puts "completed" }
      e.transitions from: [:active, :pending], to: :completed
    end
  end
end