yasm 0.0.3 → 0.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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