moody 0.1.1 → 0.2.0
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.
- data/README.md +17 -2
- data/lib/moody.rb +8 -0
- data/moody.gemspec +1 -1
- data/test/test_moody.rb +85 -43
- metadata +3 -3
data/README.md
CHANGED
@@ -7,7 +7,7 @@ object can change its behavior at runtime, depending on its internal state.
|
|
7
7
|
If you want more information about this pattern, read [the explanation by
|
8
8
|
SourceMaking](http://sourcemaking.com/design_patterns/state).
|
9
9
|
|
10
|
-
For a stupid example of how you would use this, here
|
10
|
+
For a stupid example of how you would use this, here is a traffic light:
|
11
11
|
|
12
12
|
class Stop < Moody::State
|
13
13
|
def color
|
@@ -18,6 +18,14 @@ For a stupid example of how you would use this, here's a traffic light:
|
|
18
18
|
sleep 3
|
19
19
|
switch_to Go
|
20
20
|
end
|
21
|
+
|
22
|
+
def enter
|
23
|
+
# turn on camera tu see who crosses on a red light
|
24
|
+
end
|
25
|
+
|
26
|
+
def leave
|
27
|
+
# turn off camera
|
28
|
+
end
|
21
29
|
end
|
22
30
|
|
23
31
|
class Go < Moody::State
|
@@ -56,11 +64,18 @@ For a stupid example of how you would use this, here's a traffic light:
|
|
56
64
|
traffic_light.next
|
57
65
|
end
|
58
66
|
|
67
|
+
Callbacks
|
68
|
+
---------
|
69
|
+
|
70
|
+
As you can see from the example above, Moody also provides callbacks when
|
71
|
+
entering and leaving a state. If your state classes define instance methods
|
72
|
+
`enter` and `leave`, then they will be called at the appropriate times.
|
73
|
+
|
59
74
|
Inspiration
|
60
75
|
-----------
|
61
76
|
|
62
77
|
This is a reimplementation of the State Pattern gem by Daniel Cadenas. Check out
|
63
|
-
his implementation at [http://github.com/dcadenas/state_pattern
|
78
|
+
his implementation at [his repository](http://github.com/dcadenas/state_pattern).
|
64
79
|
|
65
80
|
Installing
|
66
81
|
----------
|
data/lib/moody.rb
CHANGED
@@ -35,7 +35,15 @@ module Moody
|
|
35
35
|
end
|
36
36
|
|
37
37
|
def switch_to(next_state)
|
38
|
+
context.state.leave if context.state.respond_to?(:leave)
|
38
39
|
context.state = next_state.new(context)
|
40
|
+
context.state.enter if context.state.respond_to?(:enter)
|
41
|
+
end
|
42
|
+
|
43
|
+
def leave
|
44
|
+
end
|
45
|
+
|
46
|
+
def enter
|
39
47
|
end
|
40
48
|
end
|
41
49
|
end
|
data/moody.gemspec
CHANGED
data/test/test_moody.rb
CHANGED
@@ -1,68 +1,110 @@
|
|
1
1
|
require "test/unit"
|
2
2
|
require "moody"
|
3
|
-
require "ostruct"
|
4
3
|
|
5
|
-
class
|
6
|
-
|
7
|
-
|
8
|
-
|
4
|
+
class TestMoodyByExample < Test::Unit::TestCase
|
5
|
+
class SiegeMode < Moody::State
|
6
|
+
def strength
|
7
|
+
50
|
8
|
+
end
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
end
|
13
|
-
end
|
10
|
+
def siege_mode!
|
11
|
+
end
|
14
12
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
end
|
13
|
+
def tank_mode!
|
14
|
+
switch_to TankMode
|
15
|
+
end
|
19
16
|
|
20
|
-
|
21
|
-
|
17
|
+
def cheat!
|
18
|
+
switch_to CheatMode
|
19
|
+
end
|
22
20
|
end
|
23
|
-
end
|
24
21
|
|
25
|
-
class
|
26
|
-
|
27
|
-
|
22
|
+
class TankMode < Moody::State
|
23
|
+
def strength
|
24
|
+
20
|
25
|
+
end
|
26
|
+
|
27
|
+
def siege_mode!
|
28
|
+
switch_to SiegeMode
|
29
|
+
end
|
30
|
+
|
31
|
+
def tank_mode!
|
32
|
+
end
|
33
|
+
|
34
|
+
def cheat!
|
35
|
+
switch_to CheatMode
|
36
|
+
end
|
28
37
|
end
|
29
38
|
|
30
|
-
|
31
|
-
|
39
|
+
class CheatMode < Moody::State
|
40
|
+
def strength
|
41
|
+
100
|
42
|
+
end
|
43
|
+
|
44
|
+
def siege_mode!
|
45
|
+
switch_to SiegeMode
|
46
|
+
end
|
47
|
+
|
48
|
+
def tank_mode!
|
49
|
+
switch_to TankMode
|
50
|
+
end
|
51
|
+
|
52
|
+
def cheat!
|
53
|
+
end
|
54
|
+
|
55
|
+
def enter
|
56
|
+
$callbacks << "You're a cheat!"
|
57
|
+
end
|
58
|
+
|
59
|
+
def leave
|
60
|
+
$callbacks << "Honesty is valuable!"
|
61
|
+
end
|
32
62
|
end
|
33
|
-
end
|
34
63
|
|
35
|
-
class
|
36
|
-
|
64
|
+
class SiegeTank
|
65
|
+
extend Moody::Context
|
37
66
|
|
38
|
-
|
39
|
-
|
40
|
-
|
67
|
+
initial_state TankMode
|
68
|
+
delegate_to_state :strength, :tank_mode!, :siege_mode!, :cheat!
|
69
|
+
|
70
|
+
def attack(target)
|
71
|
+
"dealt #{strength} to #{target}"
|
72
|
+
end
|
73
|
+
end
|
41
74
|
|
42
|
-
class TestMoodyByExample < Test::Unit::TestCase
|
43
75
|
def setup
|
44
|
-
|
76
|
+
$callbacks = []
|
77
|
+
@context_class = Class.new(SiegeTank)
|
45
78
|
end
|
46
79
|
|
47
80
|
def test_initial_state
|
48
|
-
|
81
|
+
@context_class.initial_state SiegeMode
|
82
|
+
|
83
|
+
test_context = @context_class.new
|
84
|
+
assert test_context.state.is_a?(SiegeMode)
|
49
85
|
end
|
50
86
|
|
51
87
|
def test_switch_state
|
52
|
-
@
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
88
|
+
test_context = @context_class.new
|
89
|
+
test_context.siege_mode!
|
90
|
+
assert test_context.state.is_a?(SiegeMode)
|
91
|
+
test_context.tank_mode!
|
92
|
+
assert test_context.state.is_a?(TankMode)
|
93
|
+
end
|
94
|
+
|
95
|
+
def test_delegates_methods
|
96
|
+
test_context = @context_class.new
|
97
|
+
test_context.siege_mode!
|
98
|
+
assert_equal "dealt 50 to target", test_context.attack("target")
|
99
|
+
test_context.tank_mode!
|
100
|
+
assert_equal "dealt 20 to target", test_context.attack("target")
|
58
101
|
end
|
59
102
|
|
60
|
-
def
|
61
|
-
@
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
assert_equal "red", @context.color
|
103
|
+
def test_provides_callbacks
|
104
|
+
test_context = @context_class.new
|
105
|
+
test_context.cheat!
|
106
|
+
assert_equal "You're a cheat!", $callbacks.pop
|
107
|
+
test_context.siege_mode!
|
108
|
+
assert_equal "Honesty is valuable!", $callbacks.pop
|
67
109
|
end
|
68
110
|
end
|