Author image David Nicol
and 1 contributors


MooseX::Graph::Easy::StateMachine - declare state subclasses using Graph::Easy syntax and Any::Moose


Welcome to a world where a Finite State Machine drawing can go right into your source code.

    package liquor::consumer; # "I'm not an alchoholic: alchoholics go to meetings."
    use Any::Moose;
    use MooseX::Graph::Easy::StateMachine <<GRAPH;
    [BASE] - WakeUp -> [sober] - drink -> [drunk] - wait -> [sober]
    [BASE] - drink -> [drunk]
    [drunk] - passout -> [asleep] - wait -> [BASE] - wait -> [BASE]
    sub live{ my $self = shift; $self->WakeUp }
    sub liquor::consumer::sober::live {  my $self = shift; $self->drink }
    package alchoholic;
    use Any::Moose;
  BEGIN {    # this needs to be in a BEGIN block
             # so the state machine class generator
             # will be able to see the @ISA
             extends ('liquor::consumer');
    has days_sober => (isa => 'Int', is => 'rw', required => 1);
    use MooseX::Graph::Easy::StateMachine <<GRAPH;
    [sober] - GoToMeeting -> [sober]
    [drunk] - GoToMeeting -> [sober]
    [BASE] - GoToMeeting -> [sober]
    after 'drink' => sub {
      my $self = shift;
    after 'GoToMeeting' => sub {
      my $self = shift;
    sub live{ my $self = shift; $self->GoToMeeting }
  package alchoholic::sober;
    use Any::Moose;
    after ('drink' => sub {
      my $self = shift;
      $self->days_sober(0);  # the extension is automatic
    after 'GoToMeeting' => sub {
      my $self = shift;
  package Maine;
    my $Basil = alchoholic->new(3653); # Basil has been sober for ten years


This module is intended to work exactly like Graph::Easy::StateMachine only using Any::Moose OO instead,

Instead of running string-eval on the output of a layout engine, this module uses <caller()-meta->create>> and closures to generate the state transition methods.

What This Module Is Not

this module does not facilitate creating a role/trait that limits the available values that may be set into a state attribute based on inspecting what the state attribute is currently set to. Doing it that way would make sense from a flexibility and reuse standpoint, at the cost of requiring double method dispatch and a lot of dynamic checking.

surprises during development

Moose's "after" mechanism can't find methods declared like

  *{"alchoholic::sober::drink"} = sub{...}

but can find them when declared usint string eval. Mouse's can find both. Also, "after" does not affect equivalent methods in subclasses.





Copyright (C) 2011 David Nicol, <>

This module is free software; you can redistribute it and/or modify it under the terms of the Creative Commons Attribution 3.0 license

Not deleting this section from your installation is sufficient attribution.