state_pattern 1.1.0 → 1.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.rdoc +67 -23
- data/VERSION +1 -1
- data/lib/state_pattern.rb +64 -47
- data/lib/state_pattern/state.rb +8 -4
- data/state_pattern.gemspec +9 -3
- data/test/arguments_of_event_delegation_test.rb +44 -0
- data/test/hook_test.rb +83 -0
- data/test/querying_test.rb +87 -0
- data/test/state_pattern_test.rb +8 -1
- data/test/test_class_creation_helper.rb +1 -1
- data/test/test_helper.rb +0 -3
- metadata +8 -2
data/README.rdoc
CHANGED
@@ -2,40 +2,69 @@
|
|
2
2
|
|
3
3
|
A Ruby state pattern implementation.
|
4
4
|
|
5
|
+
== Example
|
6
|
+
|
7
|
+
Let's use one nice example from the AASM documentation and translate it to state_pattern (but keep in mind state_pattern is a generic gem, AASM is a Rails plugin):
|
8
|
+
|
5
9
|
require 'rubygems'
|
6
10
|
require 'state_pattern'
|
7
11
|
|
8
|
-
class
|
9
|
-
def
|
10
|
-
transition_to(
|
11
|
-
|
12
|
+
class Dating < StatePattern::State
|
13
|
+
def get_intimate
|
14
|
+
transition_to(Intimate) if stateable.drunk?
|
15
|
+
end
|
16
|
+
|
17
|
+
def get_married
|
18
|
+
transition_to(Married) if stateable.willing_to_give_up_manhood?
|
19
|
+
end
|
20
|
+
|
21
|
+
def enter
|
22
|
+
stateable.make_happy
|
23
|
+
end
|
24
|
+
|
25
|
+
def exit
|
26
|
+
stateable.make_depressed
|
12
27
|
end
|
13
28
|
end
|
14
|
-
|
15
|
-
class
|
16
|
-
def
|
17
|
-
transition_to(
|
18
|
-
|
29
|
+
|
30
|
+
class Intimate < StatePattern::State
|
31
|
+
def get_married
|
32
|
+
transition_to(Married) if stateable.willing_to_give_up_manhood?
|
33
|
+
end
|
34
|
+
|
35
|
+
def enter
|
36
|
+
stateable.make_very_happy
|
37
|
+
end
|
38
|
+
|
39
|
+
def exit
|
40
|
+
stateable.never_speak_again
|
19
41
|
end
|
20
42
|
end
|
21
|
-
|
22
|
-
class
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
def
|
28
|
-
|
43
|
+
|
44
|
+
class Married < StatePattern::State
|
45
|
+
def enter
|
46
|
+
stateable.give_up_intimacy
|
47
|
+
end
|
48
|
+
|
49
|
+
def exit
|
50
|
+
stateable.buy_exotic_car_and_wear_a_combover
|
29
51
|
end
|
30
52
|
end
|
31
53
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
54
|
+
class Relationship
|
55
|
+
include StatePattern
|
56
|
+
set_initial_state Dating
|
57
|
+
valid_transitions [Dating, :get_intimate] => Intimate, [Dating, :get_married] => Married, [Intimate, :get_married] => Married
|
36
58
|
|
37
|
-
|
38
|
-
|
59
|
+
def drunk?; @drunk; end
|
60
|
+
def willing_to_give_up_manhood?; @give_up_manhood; end
|
61
|
+
def make_happy; end
|
62
|
+
def make_depressed; end
|
63
|
+
def make_very_happy; end
|
64
|
+
def never_speak_again; end
|
65
|
+
def give_up_intimacy; end
|
66
|
+
def buy_exotic_car_and_wear_a_combover; end
|
67
|
+
end
|
39
68
|
|
40
69
|
== Validations
|
41
70
|
|
@@ -53,6 +82,21 @@ With more than one target state
|
|
53
82
|
Using event names to gain more detail
|
54
83
|
valid_transitions [Up, :switch] => [Middle, Down], [Down, :switch] => Middle, [Middle, :switch] => Up
|
55
84
|
|
85
|
+
== Enter and exit hooks
|
86
|
+
|
87
|
+
Inside your state classes, any code that you put inside the enter method will be executed when the state is instantiated.
|
88
|
+
You can also use the exit hook which is triggered when a successfull transition to another state takes place.
|
89
|
+
|
90
|
+
== Querying
|
91
|
+
|
92
|
+
The state pattern is a very dynamic way of representing a state machine, very few things are hard-coded and everything can change on runtime.
|
93
|
+
This means that the only way (apart from parsing ruby code) to get a list of the state classes and events that are used, is inspecting the valid_transitions array.
|
94
|
+
So assuming that you completely draw your state machine with valid_transitions (which is always recommended) you can use the class methods state_classes and state_events to get a list of states and events respectively.
|
95
|
+
|
96
|
+
== Installation
|
97
|
+
|
98
|
+
sudo gem install state_pattern
|
99
|
+
|
56
100
|
== Collaborate
|
57
101
|
|
58
102
|
http://github.com/dcadenas/state_pattern
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.
|
1
|
+
1.2.0
|
data/lib/state_pattern.rb
CHANGED
@@ -7,87 +7,104 @@ module StatePattern
|
|
7
7
|
end
|
8
8
|
|
9
9
|
module ClassMethods
|
10
|
-
def state_classes
|
11
|
-
state_classes_in_transisions_hash = []
|
12
|
-
|
13
|
-
if transitions_hash
|
14
|
-
state_classes_in_transisions_hash = transitions_hash.map do |from, to|
|
15
|
-
from_class = from.respond_to?(:to_ary) ? from.first : from
|
16
|
-
to_classes = to.respond_to?(:to_ary) ? to : [to]
|
17
|
-
to_classes + [from_class]
|
18
|
-
end.flatten
|
19
|
-
end
|
20
|
-
|
21
|
-
state_classes_in_transisions_hash << initial_state_class
|
22
|
-
state_classes_in_transisions_hash.uniq
|
23
|
-
end
|
24
|
-
|
25
10
|
def initial_state_class
|
26
11
|
@initial_state_class
|
27
12
|
end
|
28
13
|
|
29
14
|
def set_initial_state(state_class)
|
30
15
|
@initial_state_class = state_class
|
16
|
+
create_methods
|
17
|
+
end
|
18
|
+
|
19
|
+
def state_methods
|
20
|
+
state_classes_with_their_bases = state_classes.map{|c| c.ancestors.select{|a| a.ancestors.include?(StatePattern::State) && a != StatePattern::State}}.flatten.uniq
|
21
|
+
(state_classes_with_their_bases.map{|state_class| state_class.public_instance_methods(false)}.flatten.uniq - ["enter", "exit"]).map{|s| s.to_sym}
|
22
|
+
end
|
23
|
+
|
24
|
+
def state_events
|
25
|
+
transitions_hash.to_a.flatten.uniq.select{|t| t.respond_to?(:to_sym)}.map{|s| s.to_sym}
|
26
|
+
end
|
27
|
+
|
28
|
+
def state_classes
|
29
|
+
(transitions_hash.to_a << initial_state_class).flatten.uniq.select{|t| t.respond_to?(:ancestors) && t.ancestors.include?(StatePattern::State)}
|
31
30
|
end
|
32
31
|
|
33
32
|
def valid_transitions(transitions_hash)
|
34
33
|
@transitions_hash = transitions_hash
|
35
34
|
@transitions_hash.each do |key, value|
|
36
|
-
if !value.respond_to?(:to_ary)
|
37
|
-
@transitions_hash[key] = [value]
|
38
|
-
end
|
35
|
+
@transitions_hash[key] = [value] if !value.respond_to?(:to_ary)
|
39
36
|
end
|
37
|
+
create_methods
|
40
38
|
end
|
41
39
|
|
42
40
|
def transitions_hash
|
43
41
|
@transitions_hash
|
44
42
|
end
|
45
43
|
|
46
|
-
|
44
|
+
private
|
45
|
+
def create_methods
|
46
|
+
delegate_all_state_methods
|
47
|
+
create_query_methods
|
48
|
+
end
|
49
|
+
|
50
|
+
def delegate_all_state_methods
|
47
51
|
state_methods.each do |state_method|
|
48
52
|
define_method state_method do |*args|
|
49
|
-
|
50
|
-
end
|
53
|
+
delegate_to_state(state_method, *args)
|
54
|
+
end unless respond_to?(state_method)
|
51
55
|
end
|
52
56
|
end
|
53
57
|
|
54
|
-
def
|
55
|
-
state_classes.
|
58
|
+
def create_query_methods
|
59
|
+
state_classes.each do |state_class|
|
60
|
+
method_name = "#{underscore(state_class.name.split("::").last)}?"
|
61
|
+
define_method method_name do
|
62
|
+
current_state_instance.class == state_class
|
63
|
+
end unless respond_to?(method_name)
|
64
|
+
end
|
56
65
|
end
|
57
|
-
end
|
58
66
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
67
|
+
def underscore(camel_cased_word)
|
68
|
+
camel_cased_word.to_s.gsub(/\W/, "_")
|
69
|
+
camel_cased_word.to_s.gsub(/::/, '/').
|
70
|
+
gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
|
71
|
+
gsub(/([a-z\d])([A-Z])/,'\1_\2').
|
72
|
+
tr("-", "_").
|
73
|
+
downcase
|
74
|
+
end
|
64
75
|
end
|
65
76
|
|
66
|
-
def set_state(state_class)
|
67
|
-
|
77
|
+
def set_state(state_class = nil)
|
78
|
+
state_class ||= self.class.initial_state_class
|
79
|
+
return @current_state_instance if @current_state_instance.class == state_class
|
80
|
+
@current_state_instance = state_class.new(self, @current_state_instance)
|
68
81
|
end
|
69
|
-
|
70
|
-
def
|
71
|
-
|
72
|
-
|
82
|
+
|
83
|
+
def current_state_instance
|
84
|
+
set_state if @current_state_instance.nil?
|
85
|
+
@current_state_instance
|
73
86
|
end
|
74
87
|
|
75
|
-
def
|
76
|
-
|
77
|
-
|
88
|
+
def delegate_to_state(state_method_name, *args, &block)
|
89
|
+
@current_method = state_method_name.to_sym
|
90
|
+
self.current_state_instance.send(@current_method, *args, &block)
|
78
91
|
end
|
79
92
|
|
80
|
-
def
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
valid_transition_targets = trans[from_module] || trans[[from_module, current_event]]
|
85
|
-
valid_transition_targets && valid_transition_targets.include?(to_module)
|
93
|
+
def transition_to(next_state_class)
|
94
|
+
raise_invalid_transition_to(next_state_class) unless valid_transition?(current_state_instance.class, next_state_class)
|
95
|
+
current_state_instance.exit
|
96
|
+
set_state(next_state_class)
|
86
97
|
end
|
87
98
|
|
88
|
-
def
|
89
|
-
|
99
|
+
def raise_invalid_transition_to(state_class)
|
100
|
+
raise InvalidTransitionException.new(current_state_instance.class, state_class, @current_method)
|
90
101
|
end
|
91
|
-
end
|
92
102
|
|
103
|
+
def valid_transition?(from_state, to_state)
|
104
|
+
transitions = self.class.transitions_hash
|
105
|
+
return true if transitions.nil?
|
93
106
|
|
107
|
+
valid_transition_targets = transitions[from_state] || transitions[[from_state, @current_method]]
|
108
|
+
valid_transition_targets && valid_transition_targets.include?(to_state)
|
109
|
+
end
|
110
|
+
end
|
data/lib/state_pattern/state.rb
CHANGED
@@ -1,16 +1,20 @@
|
|
1
1
|
module StatePattern
|
2
2
|
class State
|
3
|
-
attr_reader :stateable
|
4
|
-
def initialize(stateable)
|
3
|
+
attr_reader :stateable, :previous_state
|
4
|
+
def initialize(stateable, previous_state)
|
5
5
|
@stateable = stateable
|
6
|
+
@previous_state = previous_state
|
7
|
+
enter
|
6
8
|
end
|
7
9
|
|
8
10
|
def transition_to(state_class)
|
9
11
|
@stateable.transition_to(state_class)
|
10
12
|
end
|
11
13
|
|
12
|
-
def
|
13
|
-
|
14
|
+
def enter
|
15
|
+
end
|
16
|
+
|
17
|
+
def exit
|
14
18
|
end
|
15
19
|
end
|
16
20
|
end
|
data/state_pattern.gemspec
CHANGED
@@ -2,11 +2,11 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = %q{state_pattern}
|
5
|
-
s.version = "1.
|
5
|
+
s.version = "1.2.0"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["Daniel Cadenas"]
|
9
|
-
s.date = %q{2009-
|
9
|
+
s.date = %q{2009-10-12}
|
10
10
|
s.email = %q{dcadenas@gmail.com}
|
11
11
|
s.extra_rdoc_files = [
|
12
12
|
"LICENSE",
|
@@ -23,6 +23,9 @@ Gem::Specification.new do |s|
|
|
23
23
|
"lib/state_pattern/invalid_transition_exception.rb",
|
24
24
|
"lib/state_pattern/state.rb",
|
25
25
|
"state_pattern.gemspec",
|
26
|
+
"test/arguments_of_event_delegation_test.rb",
|
27
|
+
"test/hook_test.rb",
|
28
|
+
"test/querying_test.rb",
|
26
29
|
"test/state_pattern_test.rb",
|
27
30
|
"test/test_class_creation_helper.rb",
|
28
31
|
"test/test_helper.rb",
|
@@ -35,7 +38,10 @@ Gem::Specification.new do |s|
|
|
35
38
|
s.rubygems_version = %q{1.3.3}
|
36
39
|
s.summary = %q{A Ruby state pattern implementation}
|
37
40
|
s.test_files = [
|
38
|
-
"test/
|
41
|
+
"test/arguments_of_event_delegation_test.rb",
|
42
|
+
"test/hook_test.rb",
|
43
|
+
"test/querying_test.rb",
|
44
|
+
"test/state_pattern_test.rb",
|
39
45
|
"test/test_class_creation_helper.rb",
|
40
46
|
"test/test_helper.rb",
|
41
47
|
"test/transition_validations_test.rb"
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class SampleClass
|
4
|
+
def event(arg1, arg2)
|
5
|
+
block_value = block_given? ? yield : nil
|
6
|
+
[arg1, arg2, block_value].compact.join(", ")
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
class SampleState < StatePattern::State
|
11
|
+
def event(arg1, arg2)
|
12
|
+
block_value = block_given? ? yield : nil
|
13
|
+
"state event args == " + [arg1, arg2, block_value].compact.join(", ")
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class SampleClassWithStatePattern < SampleClass
|
18
|
+
include StatePattern
|
19
|
+
set_initial_state SampleState
|
20
|
+
end
|
21
|
+
|
22
|
+
Expectations do
|
23
|
+
expect "arg1, arg2" do
|
24
|
+
sample_class_instance = ::SampleClass.new
|
25
|
+
sample_class_instance.event("arg1", "arg2")
|
26
|
+
end
|
27
|
+
|
28
|
+
expect "state event args == arg1, arg2" do
|
29
|
+
sample_class_instance = ::SampleClassWithStatePattern.new
|
30
|
+
sample_class_instance.event("arg1", "arg2")
|
31
|
+
end
|
32
|
+
|
33
|
+
=begin
|
34
|
+
PENDING
|
35
|
+
Currently using class_eval to define the delegation method (so we can pass a block)
|
36
|
+
is causing a segmention fault on 1.8.6 so we only use define_method to do the delegation
|
37
|
+
if you want to pass a block do so as a normal variable, do use yield
|
38
|
+
|
39
|
+
expect "state event args == arg1, arg2, arg3" do
|
40
|
+
sample_class_instance = ::SampleClassWithStatePattern.new
|
41
|
+
sample_class_instance.event("arg1", "arg2"){"arg3"}
|
42
|
+
end
|
43
|
+
=end
|
44
|
+
end
|
data/test/hook_test.rb
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module Hooks
|
4
|
+
class On < StatePattern::State
|
5
|
+
def press
|
6
|
+
transition_to(Off)
|
7
|
+
stateable.messages << "#{stateable.button_name} is off"
|
8
|
+
end
|
9
|
+
|
10
|
+
def enter
|
11
|
+
stateable.messages << "Entered the On state"
|
12
|
+
end
|
13
|
+
|
14
|
+
def exit
|
15
|
+
stateable.messages << "Exited the On state"
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
def private_method
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class Off < StatePattern::State
|
24
|
+
def press
|
25
|
+
transition_to(On)
|
26
|
+
stateable.messages << "#{stateable.button_name} is on"
|
27
|
+
end
|
28
|
+
|
29
|
+
def enter
|
30
|
+
stateable.messages << "Entered the Off state"
|
31
|
+
end
|
32
|
+
|
33
|
+
def exit
|
34
|
+
stateable.messages << "Exited the Off state"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
class Button
|
39
|
+
include StatePattern
|
40
|
+
set_initial_state Off
|
41
|
+
valid_transitions [On, :press] => Off, [Off, :press] => On
|
42
|
+
|
43
|
+
def button_name
|
44
|
+
"Button"
|
45
|
+
end
|
46
|
+
|
47
|
+
def messages
|
48
|
+
@messages ||= []
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
Expectations do
|
54
|
+
expect ["Entered the Off state", "Exited the Off state", "Entered the On state", "Button is on"] do
|
55
|
+
button = Hooks::Button.new
|
56
|
+
button.press
|
57
|
+
button.messages
|
58
|
+
end
|
59
|
+
|
60
|
+
expect ["Entered the Off state", "Exited the Off state", "Entered the On state", "Button is on", "Exited the On state", "Entered the Off state", "Button is off"] do
|
61
|
+
button = Hooks::Button.new
|
62
|
+
button.press
|
63
|
+
button.press
|
64
|
+
button.messages
|
65
|
+
end
|
66
|
+
|
67
|
+
expect false do
|
68
|
+
Hooks::Button.new.respond_to?(:enter)
|
69
|
+
end
|
70
|
+
|
71
|
+
expect false do
|
72
|
+
Hooks::Button.new.respond_to?(:exit)
|
73
|
+
end
|
74
|
+
|
75
|
+
expect false do
|
76
|
+
Hooks::Button.new.respond_to?(:private_method)
|
77
|
+
end
|
78
|
+
|
79
|
+
expect true do
|
80
|
+
Hooks::Button.new.respond_to?(:press)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
@@ -0,0 +1,87 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module Querying
|
4
|
+
class StateBaseBase < StatePattern::State
|
5
|
+
def common_event
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
class StateBase < StateBaseBase
|
10
|
+
def another_common_event
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class On < StateBase
|
15
|
+
def press
|
16
|
+
transition_to(Off)
|
17
|
+
end
|
18
|
+
|
19
|
+
def one_event
|
20
|
+
end
|
21
|
+
|
22
|
+
def another_event
|
23
|
+
end
|
24
|
+
|
25
|
+
def enter
|
26
|
+
end
|
27
|
+
|
28
|
+
def exit
|
29
|
+
end
|
30
|
+
private
|
31
|
+
def not_an_event
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
class Off < StateBase
|
36
|
+
def press
|
37
|
+
transition_to(On)
|
38
|
+
end
|
39
|
+
|
40
|
+
def one_event
|
41
|
+
end
|
42
|
+
|
43
|
+
def another_event
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
class Button
|
48
|
+
include StatePattern
|
49
|
+
set_initial_state On
|
50
|
+
valid_transitions [On, :press] => Off, [Off, :press] => On
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
Expectations do
|
55
|
+
expect %w(Querying::Off Querying::On) do
|
56
|
+
Querying::Button.state_classes.map{|c| c.name}.sort
|
57
|
+
end
|
58
|
+
|
59
|
+
expect ["another_common_event", "another_event", "common_event", "one_event", "press"] do
|
60
|
+
Querying::Button.state_methods.map{|s| s.to_s}.sort
|
61
|
+
end
|
62
|
+
|
63
|
+
expect [:press] do
|
64
|
+
Querying::Button.state_events
|
65
|
+
end
|
66
|
+
|
67
|
+
expect true do
|
68
|
+
Querying::Button.new.on?
|
69
|
+
end
|
70
|
+
|
71
|
+
expect false do
|
72
|
+
Querying::Button.new.off?
|
73
|
+
end
|
74
|
+
|
75
|
+
expect false do
|
76
|
+
button = Querying::Button.new
|
77
|
+
button.press
|
78
|
+
button.on?
|
79
|
+
end
|
80
|
+
|
81
|
+
expect true do
|
82
|
+
button = Querying::Button.new
|
83
|
+
button.press
|
84
|
+
button.off?
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
data/test/state_pattern_test.rb
CHANGED
@@ -6,6 +6,9 @@ module Family
|
|
6
6
|
transition_to(Lynn)
|
7
7
|
"James #{stateable.last_name}"
|
8
8
|
end
|
9
|
+
|
10
|
+
def james_method
|
11
|
+
end
|
9
12
|
end
|
10
13
|
|
11
14
|
class Lynn < StatePattern::State
|
@@ -22,7 +25,7 @@ module Family
|
|
22
25
|
|
23
26
|
#notice this method is optional, it will be delegated automatically if removed
|
24
27
|
def name
|
25
|
-
|
28
|
+
delegate_to_state :name
|
26
29
|
end
|
27
30
|
|
28
31
|
def last_name
|
@@ -50,6 +53,10 @@ Expectations do
|
|
50
53
|
member.name
|
51
54
|
end
|
52
55
|
|
56
|
+
expect true do
|
57
|
+
Family::Member.new.respond_to?(:james_method)
|
58
|
+
end
|
59
|
+
|
53
60
|
expect "on" do
|
54
61
|
with_test_class("Button", :states => ["On", "Off"], :initial_state => "Off",
|
55
62
|
:transitions => {["On", :press] => "Off", ["Off", :press] => "On"}) do
|
data/test/test_helper.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: state_pattern
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Daniel Cadenas
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-
|
12
|
+
date: 2009-10-12 00:00:00 -02:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -33,6 +33,9 @@ files:
|
|
33
33
|
- lib/state_pattern/invalid_transition_exception.rb
|
34
34
|
- lib/state_pattern/state.rb
|
35
35
|
- state_pattern.gemspec
|
36
|
+
- test/arguments_of_event_delegation_test.rb
|
37
|
+
- test/hook_test.rb
|
38
|
+
- test/querying_test.rb
|
36
39
|
- test/state_pattern_test.rb
|
37
40
|
- test/test_class_creation_helper.rb
|
38
41
|
- test/test_helper.rb
|
@@ -66,6 +69,9 @@ signing_key:
|
|
66
69
|
specification_version: 3
|
67
70
|
summary: A Ruby state pattern implementation
|
68
71
|
test_files:
|
72
|
+
- test/arguments_of_event_delegation_test.rb
|
73
|
+
- test/hook_test.rb
|
74
|
+
- test/querying_test.rb
|
69
75
|
- test/state_pattern_test.rb
|
70
76
|
- test/test_class_creation_helper.rb
|
71
77
|
- test/test_helper.rb
|