If you’re doing any significant amount of work with statmachines, you will most certainly encounter some conditional logic in your Statemachines. Take our vending machine.
When ever a coin is inserted, the invoked event will depend on whether the total amount of money inserted is sufficient to buy something.
If enough money has been tendered, the display should suggest that the customer make a selection. If insufficient money has been inserted, the customer should be prompted to insert more.
Conditional logic can be accomplished by using entry actions. See the diagram below.

Starting in the Accept Money
state, when a coin is inserted, the coin event is fired and the Statemachine transitions into the Coin Inserted
state. This is where it gets fun.
Upon entering of the Coin Inserted
state its entry event is invoked: count_amount_tendered
. This method will count the money and invoke the not_paid_yet
or paid
event accordingly. This will cause the Statemachine to transition into the appropriate state.
The Coin Inserted
state is unique. You wouldn’t expect to find the Statemachine in the Coin Inserted
state for any reason except to make this decision. Once the decision is made, the state changes. States like this are called Decision States.
Code
1require 'rubygems'
2require 'statemachine'
3
4class VendingMachineContext
5
6 attr_accessor :statemachine
7
8 def initialize
9 @amount_tendered = 0
10 end
11
12 def add_coin
13 @amount_tendered = @amount_tendered + 25
14 end
15
16 def count_amount_tendered
17 if @amount_tendered >= 100
18 @statemachine.paid
19 else
20 @statemachine.not_paid_yet
21 end
22 end
23
24 def prompt_money
25 puts "$.#{@amount_tendered}: more money please"
26 end
27
28 def prompt_selection
29 puts "please make a selection"
30 end
31end
32
33vending_machine = Statemachine.build do
34 trans :accept_money, :coin, :coin_inserted, :add_coin
35 state :coin_inserted do
36 event :not_paid_yet, :accept_money, :prompt_money
37 event :paid, :await_selection, :prompt_selection
38 on_entry :count_amount_tendered
39 end
40 context VendingMachineContext.new
41end
42vending_machine.context.statemachine = vending_machine
43
44vending_machine.coin
45vending_machine.coin
46vending_machine.coin
47vending_machine.coin
Output:
1$.25: more money please
2$.50: more money please
3$.75: more money please
4please make a selection
Next lesson: Superstates