yasm 0.0.3 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,6 @@
1
+ pkg/
2
+ *.sw?
3
+ .rvmrc
4
+ Gemfile.lock
5
+ .bundle/
6
+ *.gem
@@ -0,0 +1,10 @@
1
+ v0.0.5
2
+ -- feature: before_action and after_action callbacks on state containers (see README).
3
+
4
+ v0.0.4
5
+ -- feature: couchrest_model persistence (see README).
6
+
7
+ v0.0.2
8
+
9
+ -- feature: minimum/maximum time limits on states. (see the `State Timers` section in the README).
10
+ -- feature: exceptions are now subclassed, so that you can easily catch them.
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
@@ -0,0 +1,103 @@
1
+ This software is PUBLIC DOMAIN
2
+
3
+
4
+ ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
5
+ ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
6
+ ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
7
+ ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
8
+ ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
9
+ ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,;;iiii;;,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
10
+ ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,;ijffffffffffffffffji;,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
11
+ ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,;iffffffffffffffffffffffffffi;,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
12
+ ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, iffffffffffffffffffffffffffffffi ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
13
+ ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,ijffffffffffffffffffffffffffffffffffji,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
14
+ ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,iffffffffffffffffffffffffffffffffffffffffi,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
15
+ ,,,,,,,,,,,,,,,,,,,,,,,,,,,jffffffffffffffffffffffffffffffffffffffffffffj,,,,,,,,,,,,,,,,,,,,,,,,,,,
16
+ ,,,,,,,,,,,,,,,,,,,,,,,,,,tfffffffffffffffffffffffffffffffffffffffffffffft,,,,,,,,,,,,,,,,,,,,,,,,,,
17
+ ,,,,,,,,,,,,,,,,,,,,,,,,;ffffffffffffffffffffffffffffffffffffffffffffffffff;,,,,,,,,,,,,,,,,,,,,,,,,
18
+ ,,,,,,,,,,,,,,,,,,,,,,,ffffffffffffffffffffffjt;;,,;;tjffffffffffffffffffffff,,,,,,,,,,,,,,,,,,,,,,,
19
+ ,,,,,,,,,,,,,,,,,,,,,;fffffffffffffffffft: :tffffffffffffffffff;,,,,,,,,,,,,,,,,,,,,,
20
+ ,,,,,,,,,,,,,,,,,,,,,jfffffffffffffffft. .tffffffffffffffffj,,,,,,,,,,,,,,,,,,,,,
21
+ ,,,,,,,,,,,,,,,,,,,ifffffffffffffffi: :ifffffffffffffffi,,,,,,,,,,,,,,,,,,,
22
+ ,,,,,,,,,,,,,,,,,,tffffffffffffffi ifffffffffffffft,,,,,,,,,,,,,,,,,,
23
+ ,,,,,,,,,,,,,,,,,ifffffffffffff, ,fffffffffffffi,,,,,,,,,,,,,,,,,
24
+ ,,,,,,,,,,,,,,,,,fffffffffffffi ifffffffffffff,,,,,,,,,,,,,,,,,
25
+ ,,,,,,,,,,,,,,,;jffffffffffff ffffffffffffj;,,,,,,,,,,,,,,,
26
+ ,,,,,,,,,,,,,,,ffffffffffff: jffffffffffffff,,,,,,,,,,,,,,,
27
+ ,,,,,,,,,,,,,,ffffffffffff. jffffffffffffffff,,,,,,,,,,,,,,
28
+ ,,,,,,,,,,,,,;ffffffffffft :fffffffffffffffff;,,,,,,,,,,,,,
29
+ ,,,,,,,,,,,,,ffffffffffft ,tfffffft; jfffffffffffffffffff,,,,,,,,,,,,,
30
+ ,,,,,,,,,,,,tffffffffff. ;ffffffffffffffff; jfffffffffffffffffffft,,,,,,,,,,,,
31
+ ,,,,,,,,,,,jffffffffff: ,ffffffffffffffffffffff, jffffffffffffffffffffffj,,,,,,,,,,,
32
+ ,,,,,,,,,,,fffffffffff :ffffffffffffffffffffffff: :ffffffffffffffffffffffff,,,,,,,,,,,
33
+ ,,,,,,,,,,iffffffffff ,jfffffffffffffffffffffffff jfffffffffffffffffffffffffi,,,,,,,,,,
34
+ ,,,,,,,,,,ffffffffffi tffffffffffffffffffffffffff jfffffffffffffff iffffffffff,,,,,,,,,,
35
+ ,,,,,,,,,ifffffffff, jfffffffffffffffffffffffff, jfffffffffffffff ,fffffffffi,,,,,,,,,
36
+ ,,,,,,,,,jfffffffff :ffffffffffffffffffffffffff :fffffffffffffff; fffffffffj,,,,,,,,,
37
+ ,,,,,,,, fffffffffi jffffffffffffffffffffffffff jfffffffffffffff ifffffffff ,,,,,,,,
38
+ ,,,,,,,,ifffffffff tffffffffffffffffffffffffff jfffffffffffffff fffffffffi,,,,,,,,
39
+ ,,,,,,,;fffffffffi :fffffffffffffffffffffffff, jfffffffffffffff ifffffffff;,,,,,,,
40
+ ,,,,,,,ifffffffff: jfffffffffffffffffffffffff :fffffffffffffff; :fffffffffi,,,,,,,
41
+ ,,,,,,,ffffffffff :fffffffffffffffffffffffff jfffffffffffffff ffffffffff,,,,,,,
42
+ ,,,,,,,ffffffffft ,fffffffffffffffff; jfffffffffffffff t, tfffffffff,,,,,,,
43
+ ,,,,,,;fffffffff ffffffffffffffff jfffffffffffffff tff fffffffff;,,,,,,
44
+ ,,,,,,ifffffffft fffffffffffffff, :fffffffffffffff;.fff tffffffffi,,,,,,
45
+ ,,,,,,jffffffff: ;ffffffffffffff. jfffffffffffffff .ffff; :ffffffffj,,,,,,
46
+ ,,,,,,fffffffff ffffffffffffff, jfffffffffffffff tffffff fffffffff,,,,,,
47
+ ,,,,,,fffffffff fffffffffffff jfffffffffffffff tfffffff fffffffff,,,,,,
48
+ ,,,,,,fffffffff fffffffffffff :fffffffffffffff; ........ fffffffff,,,,,,
49
+ ,,,,,;ffffffffj ,ffffffffffff; jfffffffffffffff jffffffff;,,,,,
50
+ ,,,,,;ffffffffi tffffffffffff jfffffffffffffff iffffffff;,,,,,
51
+ ,,,,,;ffffffff; fffffffffffff jfffffffffffffff ;ffffffff;,,,,,
52
+ ,,,,,;ffffffff; fffffffffffff :fffffffffffffff; ;ffffffff;,,,,,
53
+ ,,,,,iffffffff, fffffffffffff jfffffffffffffff ,ffffffffi,,,,,
54
+ ,,,,,iffffffff, fffffffffffff jfffffffffffffff ,ffffffffi,,,,,
55
+ ,,,,,;ffffffff; fffffffffffff jfffffffffffffff ;ffffffff;,,,,,
56
+ ,,,,,;ffffffff; fffffffffffff :fffffffffffffff; ;ffffffff;,,,,,
57
+ ,,,,,;ffffffffi tffffffffffff jfffffffffffffff iffffffff;,,,,,
58
+ ,,,,,;ffffffffj ,fffffffffff jfffffffffffffff jffffffff;,,,,,
59
+ ,,,,,,fffffffff fffffffff, jfffffffffffffff jjjjjjjjjjjjj fffffffff,,,,,,
60
+ ,,,,,,fffffffff fffffffff :fffffffffffffff; .fffffffffffff fffffffff,,,,,,
61
+ ,,,,,,fffffffff ffffffff jfffffffffffffff ,ffffffffffffff fffffffff,,,,,,
62
+ ,,,,,,jffffffff: ;ffffff jfffffffffffffff .ffffffffffffff; :ffffffffj,,,,,,
63
+ ,,,,,,ifffffffft ffff, jfffffffffffffff ,fffffffffffffff tffffffffi,,,,,,
64
+ ,,,,,,;fffffffff ffff :fffffffffffffff; ffffffffffffffff fffffffff;,,,,,,
65
+ ,,,,,,,ffffffffft ,ff jfffffffffffffff ifffffffffffffffff, tfffffffff,,,,,,,
66
+ ,,,,,,,ffffffffff : jfffffffffffffff tfffffffffffffffffffffff: ffffffffff,,,,,,,
67
+ ,,,,,,,ifffffffff: jfffffffffffffff tfffffffffffffffffffffffj :fffffffffi,,,,,,,
68
+ ,,,,,,,;fffffffffi :fffffffffffffff;.ffffffffffffffffffffffff: ifffffffff;,,,,,,,
69
+ ,,,,,,,,ifffffffff jfffffffffffffff .fffffffffffffffffffffffft fffffffffi,,,,,,,,
70
+ ,,,,,,,, fffffffffi jfffffffffffffff tffffffffffffffffffffffffj ifffffffff ,,,,,,,,
71
+ ,,,,,,,,,jfffffffff jfffffffffffffff tffffffffffffffffffffffff: fffffffffj,,,,,,,,,
72
+ ,,,,,,,,,ifffffffff, :fffffffffffffff;.ffffffffffffffffffffffffj ,fffffffffi,,,,,,,,,
73
+ ,,,,,,,,,,ffffffffffi jfffffffffffffff .fffffffffffffffffffffffft iffffffffff,,,,,,,,,,
74
+ ,,,,,,,,,,iffffffffff jfffffffffffffff tfffffffffffffffffffffffj, ffffffffffi,,,,,,,,,,
75
+ ,,,,,,,,,,,ffffffffffffffffffffffffff tfffffffffffffffffffffff: fffffffffff,,,,,,,,,,,
76
+ ,,,,,,,,,,,jffffffffffffffffffffffff; ,ffffffffffffffffffffff, :ffffffffffj,,,,,,,,,,,
77
+ ,,,,,,,,,,,,tffffffffffffffffffffff ;ffffffffffffffff; .fffffffffft,,,,,,,,,,,,
78
+ ,,,,,,,,,,,,,fffffffffffffffffffff ,tfffffft; tfffffffffff,,,,,,,,,,,,,
79
+ ,,,,,,,,,,,,,;fffffffffffffffffff tfffffffffff;,,,,,,,,,,,,,
80
+ ,,,,,,,,,,,,,,ffffffffffffffffff; .ffffffffffff,,,,,,,,,,,,,,
81
+ ,,,,,,,,,,,,,,,ffffffffffffffff :ffffffffffff,,,,,,,,,,,,,,,
82
+ ,,,,,,,,,,,,,,,;jfffffffffffff ffffffffffffj;,,,,,,,,,,,,,,,
83
+ ,,,,,,,,,,,,,,,,,fffffffffffffi ifffffffffffff,,,,,,,,,,,,,,,,,
84
+ ,,,,,,,,,,,,,,,,,ifffffffffffff, ,fffffffffffffi,,,,,,,,,,,,,,,,,
85
+ ,,,,,,,,,,,,,,,,,,tffffffffffffffi ifffffffffffffft,,,,,,,,,,,,,,,,,,
86
+ ,,,,,,,,,,,,,,,,,,,ifffffffffffffffi: :ifffffffffffffffi,,,,,,,,,,,,,,,,,,,
87
+ ,,,,,,,,,,,,,,,,,,,,,jfffffffffffffffft. .tffffffffffffffffj,,,,,,,,,,,,,,,,,,,,,
88
+ ,,,,,,,,,,,,,,,,,,,,,;fffffffffffffffffft: :tffffffffffffffffff;,,,,,,,,,,,,,,,,,,,,,
89
+ ,,,,,,,,,,,,,,,,,,,,,,,ffffffffffffffffffffffjt;;,,;;tjffffffffffffffffffffff,,,,,,,,,,,,,,,,,,,,,,,
90
+ ,,,,,,,,,,,,,,,,,,,,,,,,;ffffffffffffffffffffffffffffffffffffffffffffffffff;,,,,,,,,,,,,,,,,,,,,,,,,
91
+ ,,,,,,,,,,,,,,,,,,,,,,,,,,tfffffffffffffffffffffffffffffffffffffffffffffft,,,,,,,,,,,,,,,,,,,,,,,,,,
92
+ ,,,,,,,,,,,,,,,,,,,,,,,,,,,jffffffffffffffffffffffffffffffffffffffffffffj,,,,,,,,,,,,,,,,,,,,,,,,,,,
93
+ ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,iffffffffffffffffffffffffffffffffffffffffi,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
94
+ ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,ijffffffffffffffffffffffffffffffffffji,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
95
+ ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, iffffffffffffffffffffffffffffffi ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
96
+ ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,;iffffffffffffffffffffffffffi;,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
97
+ ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,;ijffffffffffffffffji;,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
98
+ ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,;;iiii;;,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
99
+ ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
100
+ ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
101
+ ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
102
+ ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
103
+ ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
@@ -359,6 +359,183 @@ long time. Like, long enough to cause a state transition domino effect. Let's mo
359
359
  Notice that this domino effect happened lazily when you call the `do!` method, or the `context.state.value` methods. Quite nice for systems where
360
360
  you persist your state to a db.
361
361
 
362
+
363
+ ## Persistence
364
+
365
+ How do you persist your state to a database? YASM will automatically persist/load your states to/from the database; it supports (or plans to support) the following ORMs:
366
+
367
+ * couchrest_model (as of version 0.0.4)
368
+ * mongoid (coming soon)
369
+ * active_record (coming soon)
370
+
371
+ For example, let's suppose our vending machine context was actually a CouchDB document, modelled with CouchRest::Model:
372
+
373
+ class VendingMachine < CouchRest::Model::Base
374
+ include Yasm::Context
375
+
376
+ start :waiting
377
+ end
378
+
379
+ #.....
380
+
381
+ By simply mixing Yasm::Context into the document, our states will be automatically persisted to the database and loaded from the database.
382
+
383
+
384
+ ## Anonymous and Named States
385
+
386
+ Up till now, we've been utilizing the anonymous state on our context. In other words, because we didn't wrap our `start :waiting` inside a `state` call, YASM
387
+ assumed that we were simply going to be using the anonymous state on our class. Also, when we've called the `do!` method, we've called it directly on our context,
388
+ which again assumes that you're attempting to apply an action to the anonymous state on your context.
389
+
390
+ What's an example of a named state? Perhaps we'd like to manage the electricity on our vending machine with a state machine. To do so, we'd simply:
391
+
392
+ class VendingMachine
393
+ include Yasm::Context
394
+
395
+ start :waiting
396
+
397
+ state(:electricity) do
398
+ start :on
399
+ end
400
+ end
401
+
402
+ class Waiting; include Yasm::State; end
403
+ class Vending; include Yasm::State; end
404
+ class On; include Yasm::State; end
405
+ class Off; include Yasm::State; end
406
+
407
+ class Unplug
408
+ include Yasm::Action
409
+
410
+ triggers :off
411
+ end
412
+
413
+ class Plugin
414
+ include Yasm::Action
415
+
416
+ triggers :on
417
+ end
418
+
419
+ class Select
420
+ include Yasm::Action
421
+
422
+ triggers :vending
423
+ end
424
+
425
+ Now our VendingMachine has two managed states: the anonymous state (that start in the `Waiting` state), and the "electricity" state (that starts in the `On` state).
426
+
427
+ We can apply actions to each of these states independently:
428
+
429
+ v = VendingMachine.new
430
+
431
+ puts v.state.value
432
+ #==> Waiting
433
+
434
+ puts v.electricity.value
435
+ #==> On
436
+
437
+ v.do! Select
438
+
439
+ puts v.state.value
440
+ #==> Vending
441
+
442
+ v.electricity.do! Unplug
443
+
444
+ puts v.electricity.value
445
+ #==> Off
446
+
447
+ ## Action Callbacks
448
+
449
+ How do you run a method before or after an action is applied to a yasm state within your context? Yasm::Context gives you the following two callback macros for this purpose:
450
+ `before_action` and `after_action`. They each accept two parameters: a symbol representing the method on the context you'd like called, and an options hash, where you
451
+ can specify `:only` or `:except` constraints.
452
+
453
+ For example:
454
+
455
+ class Human
456
+ include Yasm::Context
457
+
458
+ start :alive
459
+ before_action :weigh_options, :except => :jump_off_building
460
+ after_action :consider_results, :only => :jump_off_building
461
+
462
+ private
463
+ def weigh_options
464
+ puts "You could, alternatively, jump off a building."
465
+ end
466
+
467
+ def consider_results
468
+ puts "Splendid!"
469
+ end
470
+ end
471
+
472
+ class Alive; include Yasm::State; end
473
+ class Dead; include Yasm::State; end
474
+
475
+ class GoToWork
476
+ include Yasm::Action
477
+ end
478
+
479
+ class JumpOffBuilding
480
+ include Yasm::Action
481
+ triggers :dead
482
+
483
+ def execute
484
+ puts "Weeeeeee!"
485
+ end
486
+ end
487
+
488
+ Now, when we apply actions to the anonymous state, before and after actions will run when appropriate:
489
+
490
+ you = Human.new
491
+
492
+ you.do! GoToWork
493
+ #==> "You could, alternatively, jump off a building."
494
+
495
+ you.do! JumpOffBuilding
496
+ #==> "Weeeeeee!"
497
+ #==> "Splendid!"
498
+
499
+ Just as you can use `before_action` and `after_action` with the anonymous state, you can use it with named states as well:
500
+
501
+ class VendingMachine
502
+ include Yasm::Context
503
+
504
+ state(:electricity) do
505
+ start :on
506
+ before_action :warn, :only => :unplug
507
+ after_action :sigh
508
+ end
509
+
510
+ private
511
+ def warn
512
+ puts "Wait! Don't unplug me!!!"
513
+ end
514
+
515
+ def sigh
516
+ puts "sigh...."
517
+ end
518
+ end
519
+
520
+ class On; include Yasm::State; end
521
+ class Off; include Yasm::State; end
522
+
523
+ class Unplug
524
+ include Yasm::Action
525
+ triggers :off
526
+
527
+ def execute
528
+ puts "unplugging...."
529
+ end
530
+ end
531
+
532
+ v = VendingMachine.new
533
+
534
+ v.electricity.do! Unplug
535
+ #==> "Wait! Don't unplug me!!!"
536
+ #==> "unplugging...."
537
+ #==> "sigh...."
538
+
362
539
  ## PUBLIC DOMAIN
363
540
 
364
541
  This software is committed to the public domain. No license. No copyright. DO ANYTHING!
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.3
1
+ 0.0.6
@@ -0,0 +1,22 @@
1
+ Feature: Action Callbacks
2
+ As a programmer
3
+ I want to have before and after hooks into actions
4
+ So that I can customize my state machine
5
+
6
+ Scenario: After Action callback
7
+ Given a context that I intend to attach action callbacks to
8
+ When I create an after action callback with no constraints
9
+ Then that callback should be called after all actions
10
+ When I create an after action callback with an `only` constraint
11
+ Then that callback should be called only when the particular action(s) run
12
+ When I create an after action callback with an `except` constraint
13
+ Then that callback should not be called when the particular action(s) run
14
+
15
+ Scenario: Before Action callback
16
+ Given a context that I intend to attach before action callbacks to
17
+ When I create a before action callback with no constraints
18
+ Then that callback should be called before all actions
19
+ When I create a before action callback with an `only` constraint
20
+ Then that before callback should be called only when the particular action(s) run
21
+ When I create a before action callback with an `except` constraint
22
+ Then that before callback should not be called when the particular action(s) run
@@ -0,0 +1,9 @@
1
+ Feature: Actions
2
+ As a programmer
3
+ I want to be able to apply actions to a state
4
+ So that I can cause the state to transition
5
+
6
+ Scenario: Applying actions to a state
7
+ Given a context
8
+ When I apply an action to it that triggers a state transition
9
+ Then the state should transition appropriately
@@ -0,0 +1,14 @@
1
+ Feature:
2
+ As a programmer
3
+ I want to declare a state as FINAL
4
+ So that I can forbid any futher actions or state transitions
5
+
6
+ Scenario: Declaring a state FINAL
7
+ Given a state that I intend to declare final
8
+ When I declare it final
9
+ Then it should return true when asked if it's a FINAL state
10
+
11
+ Scenario: Applying an action to a FINAL state
12
+ Given a final state
13
+ When I attempt to apply an action to it
14
+ Then I should get an exception
@@ -0,0 +1,22 @@
1
+ @couch
2
+ Feature: CouchRest::Model Persistance
3
+ As a CouchDB hacker
4
+ I want the states on my CouchRest::Mode::Base context persisted to CouchDB
5
+ So that I can incorporate YASM into my relaxing database environment
6
+
7
+ Scenario: Yasm::Persistence::CouchRest::Model should be auto included when Yasm::Context is included inside a CouchRest::Model::Base derived class
8
+ Given a class that inherits from CouchRest::Model::Base
9
+ When I mix Yasm::Context into it
10
+ Then Yasm::Persistence::CouchRest::Model should be autoincluded as well
11
+
12
+ Scenario: Saving state to CouchRest::Model::Base derived classes
13
+ Given a couchrest model context
14
+ When I save that context to CouchDB
15
+ Then the states should be saved in the document
16
+
17
+ Scenario: Loading state from CouchRest::Model::Base derived classes
18
+ Given a couchrest model context with state saved in the database
19
+ When I load that context
20
+ Then the states should be restored
21
+ And the states should be fast forwarded
22
+
@@ -0,0 +1,13 @@
1
+ Feature: State's that limit actions
2
+ As a programmer
3
+ I want to limit the actions that can be applied to a state
4
+ So that I can control the workflow of my state machine
5
+
6
+ Scenario: Declaring valid actions
7
+ Given a state
8
+ When I declare that only certain actions can be applied to it
9
+ Then those actions should be stored on the state class
10
+
11
+ Scenario: Determing if an action is valid for a given state
12
+ Given a state with limited actions
13
+ Then I should be able to determine whether a given action is valid for a given state
@@ -0,0 +1,29 @@
1
+ Feature: Time limits on states
2
+ As a programmer
3
+ I want to be able to put minimum and maximum time limits on states
4
+ So that I can simulate better the real world
5
+
6
+ Scenario: Declaring a minimum time limit
7
+ Given a state that I intend to declare a minimum time limit on
8
+ When I declare a minimum time limit on it
9
+ Then it should store that time limit on the state class
10
+
11
+ Scenario: Applying an action to a state with a minimum time limit
12
+ Given a state that has a minimum time limit
13
+ When I apply an action to that state before its minimum time limit has been reached
14
+ Then I should get a minimum time limit exception
15
+ When I apply an action to that state after its minimum time limit has been reached
16
+ Then I should not get a minimum time limit exception
17
+
18
+ Scenario: Declaring a maximum time limit
19
+ Given a state that I intend to declare a maximum time limit on
20
+ When I declare a maximum time limit on it without an action
21
+ Then it should raise an argument error exception
22
+ When I declare a maximum time limit on it with an action
23
+ Then it should store that maximum time limit and action on the state class
24
+
25
+ Scenario: State transition dominoe with max time limits
26
+ Given a context with the potential for a max time limit dominoe effect
27
+ When I wait long enough to cause the dominoe effect
28
+ Then the dominoe effect should occur when I ask for the state
29
+ And the dominoe effect should occur when I attempt to apply an action to the context
@@ -0,0 +1,190 @@
1
+ Given /^a context that I intend to attach action callbacks to$/ do
2
+ class ActionCallbackContext
3
+ include Yasm::Context
4
+ start :action_callback_state
5
+ end
6
+
7
+ class ActionCallbackState
8
+ include Yasm::State
9
+ end
10
+
11
+ class Action1; include Yasm::Action; end
12
+ class Action2; include Yasm::Action; end
13
+ class Action3; include Yasm::Action; end
14
+ class Action4; include Yasm::Action; end
15
+ end
16
+
17
+ When /^I create an after action callback with no constraints$/ do
18
+ class ActionCallbackContext
19
+ attr_accessor :counter
20
+ after_action :increment_counter
21
+
22
+ def initialize
23
+ @counter = 0
24
+ end
25
+
26
+ private
27
+ def increment_counter
28
+ @counter += 1
29
+ end
30
+ end
31
+ end
32
+
33
+ Then /^that callback should be called after all actions$/ do
34
+ context = ActionCallbackContext.new
35
+ context.counter.should == 0
36
+ context.do! Action1
37
+ context.counter.should == 1
38
+ context.do! Action2
39
+ context.counter.should == 2
40
+ context.do! Action3
41
+ context.counter.should == 3
42
+ context.do! Action4
43
+ context.counter.should == 4
44
+ end
45
+
46
+ When /^I create an after action callback with an `only` constraint$/ do
47
+ class ActionCallbackContext
48
+ after_action :decrement_counter, :only => [:action1, :action2]
49
+
50
+ private
51
+ def decrement_counter
52
+ @counter -= 1
53
+ end
54
+ end
55
+ end
56
+
57
+ Then /^that callback should be called only when the particular action\(s\) run$/ do
58
+ context = ActionCallbackContext.new
59
+ context.counter.should == 0
60
+ context.do! Action1
61
+ context.counter.should == 0
62
+ context.do! Action2
63
+ context.counter.should == 0
64
+ context.do! Action3
65
+ context.counter.should == 1
66
+ context.do! Action4
67
+ context.counter.should == 2
68
+ end
69
+
70
+ When /^I create an after action callback with an `except` constraint$/ do
71
+ class ActionCallbackContext
72
+ after_action :double_counter, :except => :action3
73
+
74
+ private
75
+ def double_counter
76
+ @counter *= 2
77
+ end
78
+ end
79
+ end
80
+
81
+ Then /^that callback should not be called when the particular action\(s\) run$/ do
82
+ context = ActionCallbackContext.new
83
+ context.counter.should == 0
84
+ context.do! Action3
85
+ context.counter.should == 1
86
+ context.do! Action3
87
+ context.counter.should == 2
88
+ context.do! Action4
89
+ context.counter.should == 6
90
+ context.do! Action4
91
+ context.counter.should == 14
92
+ context.do! Action1
93
+ context.counter.should == 28
94
+ end
95
+
96
+
97
+ Given /^a context that I intend to attach before action callbacks to$/ do
98
+ class BeforeActionCallbackContext
99
+ include Yasm::Context
100
+ start :action_callback_state
101
+ end
102
+ end
103
+
104
+ When /^I create a before action callback with no constraints$/ do
105
+ class BeforeActionCallbackContext
106
+ attr_accessor :counter
107
+ before_action :increment_counter
108
+
109
+ def initialize
110
+ @counter = 0
111
+ end
112
+
113
+ private
114
+ def increment_counter
115
+ @counter += 1
116
+ end
117
+ end
118
+
119
+ class ActionCallbackState
120
+ include Yasm::State
121
+ end
122
+
123
+ class Action1; include Yasm::Action; end
124
+ class Action2; include Yasm::Action; end
125
+ class Action3; include Yasm::Action; end
126
+ class Action4; include Yasm::Action; end
127
+ end
128
+
129
+ Then /^that callback should be called before all actions$/ do
130
+ context = BeforeActionCallbackContext.new
131
+ context.counter.should == 0
132
+ context.do! Action1
133
+ context.counter.should == 1
134
+ context.do! Action2
135
+ context.counter.should == 2
136
+ context.do! Action3
137
+ context.counter.should == 3
138
+ context.do! Action4
139
+ context.counter.should == 4
140
+ end
141
+
142
+ When /^I create a before action callback with an `only` constraint$/ do
143
+ class BeforeActionCallbackContext
144
+ before_action :decrement_counter, :only => [:action1, :action2]
145
+
146
+ private
147
+ def decrement_counter
148
+ @counter -= 1
149
+ end
150
+ end
151
+ end
152
+
153
+ Then /^that before callback should be called only when the particular action\(s\) run$/ do
154
+ context = BeforeActionCallbackContext.new
155
+ context.counter.should == 0
156
+ context.do! Action1
157
+ context.counter.should == 0
158
+ context.do! Action2
159
+ context.counter.should == 0
160
+ context.do! Action3
161
+ context.counter.should == 1
162
+ context.do! Action4
163
+ context.counter.should == 2
164
+ end
165
+
166
+ When /^I create a before action callback with an `except` constraint$/ do
167
+ class BeforeActionCallbackContext
168
+ before_action :double_counter, :except => :action3
169
+
170
+ private
171
+ def double_counter
172
+ @counter *= 2
173
+ end
174
+ end
175
+ end
176
+
177
+ Then /^that before callback should not be called when the particular action\(s\) run$/ do
178
+ context = BeforeActionCallbackContext.new
179
+ context.counter.should == 0
180
+ context.do! Action3
181
+ context.counter.should == 1
182
+ context.do! Action3
183
+ context.counter.should == 2
184
+ context.do! Action4
185
+ context.counter.should == 6
186
+ context.do! Action4
187
+ context.counter.should == 14
188
+ context.do! Action1
189
+ context.counter.should == 28
190
+ end