simple_state_machine 0.5.2 → 0.6.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/build.yml +46 -0
  3. data/.gitignore +3 -0
  4. data/.travis.yml +17 -0
  5. data/Changelog.rdoc +16 -0
  6. data/Gemfile +7 -0
  7. data/README.rdoc +154 -99
  8. data/examples/conversation.rb +5 -5
  9. data/examples/lamp.rb +5 -5
  10. data/examples/relationship.rb +8 -8
  11. data/examples/traffic_light.rb +3 -3
  12. data/examples/user.rb +8 -4
  13. data/gemfiles/Gemfile.activerecord-5.2.x +9 -0
  14. data/gemfiles/Gemfile.activerecord-6.0.x +9 -0
  15. data/gemfiles/Gemfile.activerecord-6.1.x +8 -0
  16. data/gemfiles/Gemfile.activerecord-main.x +9 -0
  17. data/gemfiles/Gemfile.basic +6 -0
  18. data/lib/simple_state_machine/.DS_Store +0 -0
  19. data/lib/simple_state_machine/active_record.rb +2 -64
  20. data/lib/simple_state_machine/decorator/active_record.rb +68 -0
  21. data/lib/simple_state_machine/decorator/default.rb +91 -0
  22. data/lib/simple_state_machine/railtie.rb +1 -1
  23. data/lib/simple_state_machine/simple_state_machine.rb +8 -251
  24. data/lib/simple_state_machine/state_machine.rb +88 -0
  25. data/lib/simple_state_machine/state_machine_definition.rb +72 -0
  26. data/lib/simple_state_machine/tools/graphviz.rb +21 -0
  27. data/lib/simple_state_machine/tools/inspector.rb +44 -0
  28. data/lib/simple_state_machine/transition.rb +40 -0
  29. data/lib/simple_state_machine/version.rb +1 -1
  30. data/lib/simple_state_machine.rb +13 -3
  31. data/lib/tasks/graphviz.rake +31 -0
  32. data/simple_state_machine.gemspec +14 -24
  33. data/spec/.DS_Store +0 -0
  34. data/spec/active_record_spec.rb +216 -179
  35. data/spec/{decorator_spec.rb → decorator/default_spec.rb} +32 -32
  36. data/spec/examples_spec.rb +17 -17
  37. data/spec/mountable_spec.rb +26 -14
  38. data/spec/simple_state_machine_spec.rb +128 -92
  39. data/spec/spec_helper.rb +18 -5
  40. data/spec/state_machine_definition_spec.rb +48 -34
  41. data/spec/state_machine_spec.rb +36 -2
  42. data/spec/tools/graphviz_spec.rb +30 -0
  43. data/spec/tools/inspector_spec.rb +70 -0
  44. metadata +54 -128
  45. data/autotest/discover.rb +0 -1
  46. data/lib/tasks/graphiz.rake +0 -13
  47. data/rails/graphiz.rake +0 -16
@@ -1,25 +1,25 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
1
+ require 'spec_helper'
2
2
 
3
3
  describe SimpleStateMachine::StateMachineDefinition do
4
4
 
5
- before do
6
- @klass = Class.new do
5
+ let(:klass) do
6
+ Class.new do
7
7
  extend SimpleStateMachine
8
8
  def initialize(state = 'state1')
9
9
  @state = state
10
10
  end
11
- event :event1, :state1 => :state2, :state2 => :state3
11
+ event :event1, :state1 => :state2, :state2 => :state3
12
12
  end
13
- @smd = @klass.state_machine_definition
14
13
  end
14
+ let(:smd) { klass.state_machine_definition }
15
15
 
16
16
  it "is inherited by subclasses" do
17
- example = Class.new(@klass).new
18
- example.should be_state1
19
- example.event1
20
- example.should be_state2
21
- example.event1
22
- example.should be_state3
17
+ subject = Class.new(klass).new
18
+ expect(subject).to be_state1
19
+ subject.event1
20
+ expect(subject).to be_state2
21
+ subject.event1
22
+ expect(subject).to be_state3
23
23
  end
24
24
 
25
25
  describe '#state_method' do
@@ -39,51 +39,65 @@ describe SimpleStateMachine::StateMachineDefinition do
39
39
  end
40
40
 
41
41
  it "is used when changing state" do
42
- subject.ssm_state.should == 'state1'
42
+ expect(subject.ssm_state).to eq('state1')
43
43
  subject.event1
44
- subject.ssm_state.should == 'state2'
44
+ expect(subject.ssm_state).to eq('state2')
45
45
  subject.event2
46
- subject.ssm_state.should == 'state3'
46
+ expect(subject.ssm_state).to eq('state3')
47
47
  end
48
48
 
49
49
  it "works with state helper methods" do
50
- subject.should be_state1
50
+ expect(subject).to be_state1
51
51
  subject.event1
52
- subject.should be_state2
52
+ expect(subject).to be_state2
53
53
  subject.event2
54
- subject.should be_state3
54
+ expect(subject).to be_state3
55
55
  end
56
-
56
+
57
57
  it "raise an error if an invalid state_transition is called" do
58
- lambda { subject.event2 }.should raise_error(SimpleStateMachine::IllegalStateTransitionError, "You cannot 'event2' when state is 'state1'")
58
+ expect { subject.event2 }.to raise_error(SimpleStateMachine::IllegalStateTransitionError, "You cannot 'event2' when state is 'state1'")
59
59
  end
60
60
 
61
61
  end
62
62
 
63
- describe "#transitions" do
64
- it "has a list of transitions" do
65
- @smd.transitions.should be_a(Array)
66
- @smd.transitions.first.should be_a(SimpleStateMachine::Transition)
63
+ describe '#default_error_state' do
64
+ subject do
65
+ klass = Class.new do
66
+ attr_reader :state
67
+ extend SimpleStateMachine
68
+ state_machine_definition.default_error_state = :failed
69
+
70
+ def initialize(state = 'state1')
71
+ @state = state
72
+ end
73
+
74
+ def event1
75
+ raise "Some error during event"
76
+ end
77
+ event :event1, :state1 => :state2
78
+ end
79
+ klass.new
67
80
  end
68
- end
69
81
 
70
- describe "#to_s" do
71
- it "converts to readable string format" do
72
- @smd.to_s.should =~ Regexp.new("state1.event1! => state2")
82
+ it "is set when an error occurs during an event" do
83
+ expect(subject.state).to eq('state1')
84
+ subject.event1
85
+ expect(subject.state).to eq('failed')
73
86
  end
74
87
  end
75
88
 
76
- describe "#to_graphiz_dot" do
77
- it "converts to graphiz dot format" do
78
- @smd.to_graphiz_dot.should == %("state1"->"state2"[label=event1];"state2"->"state3"[label=event1])
89
+ describe "#transitions" do
90
+ it "has a list of transitions" do
91
+ expect(smd.transitions).to be_a(Array)
92
+ expect(smd.transitions.first).to be_a(SimpleStateMachine::Transition)
79
93
  end
80
94
  end
81
95
 
82
- describe "#google_chart_url" do
83
- it "shows the state and event dependencies as a Google chart" do
84
- puts "http://chart.googleapis.com/chart?cht=gv&chl=digraph{#{::CGI.escape @smd.to_graphiz_dot}}"
85
- @smd.google_chart_url.should == "http://chart.googleapis.com/chart?cht=gv&chl=digraph{#{::CGI.escape @smd.to_graphiz_dot}}"
96
+ describe "#to_s" do
97
+ it "converts to readable string format" do
98
+ expect(smd.to_s).to match(Regexp.new("state1.event1! => state2"))
86
99
  end
87
100
  end
101
+
88
102
  end
89
103
 
@@ -14,11 +14,45 @@ describe SimpleStateMachine::StateMachine do
14
14
  end
15
15
 
16
16
  it "returns the next state for the event and current state" do
17
- subject.next_state('event1').should == 'state2'
17
+ expect(subject.next_state('event1')).to eq('state2')
18
18
  end
19
19
 
20
20
  it "returns nil if no next state for the event and current state exists" do
21
- subject.next_state('event2').should be_nil
21
+ expect(subject.next_state('event2')).to be_nil
22
+ end
23
+ end
24
+
25
+ describe "#raised_error" do
26
+ context "given an error can be caught" do
27
+ let(:class_with_error) do
28
+ Class.new do
29
+ extend SimpleStateMachine
30
+ def initialize(state = 'state1'); @state = state; end
31
+ def raise_error
32
+ raise "Something went wrong"
33
+ end
34
+ event :raise_error, :state1 => :state2,
35
+ RuntimeError => :failed
36
+ event :retry, :failed => :success
37
+ end
38
+ end
39
+
40
+ subject do
41
+ class_with_error.new.tap{|i| i.raise_error }
42
+ end
43
+
44
+ it "the raised error is accessible" do
45
+ raised_error = subject.state_machine.raised_error
46
+ expect(raised_error).to be_a(RuntimeError)
47
+ expect(raised_error.message).to eq("Something went wrong")
48
+ end
49
+
50
+ it "the raised error is set to nil on the next transition" do
51
+ expect(subject.state_machine.raised_error).to be
52
+ subject.retry
53
+ expect(subject.state_machine.raised_error).not_to be
54
+ end
55
+
22
56
  end
23
57
  end
24
58
 
@@ -0,0 +1,30 @@
1
+ require 'spec_helper'
2
+
3
+ describe SimpleStateMachine::Tools::Graphviz do
4
+
5
+ before do
6
+ @klass = Class.new do
7
+ extend SimpleStateMachine
8
+ def initialize(state = 'state1')
9
+ @state = state
10
+ end
11
+ event :event1, :state1 => :state2, :state2 => :state3
12
+ end
13
+ @smd = @klass.state_machine_definition
14
+ end
15
+
16
+ describe "#to_graphviz_dot" do
17
+ it "converts to graphviz dot format" do
18
+ expect(@smd.to_graphviz_dot).to eq(%(digraph G {\n"state1"->"state2"[label=event1];\n"state2"->"state3"[label=event1]\n}))
19
+ end
20
+ end
21
+
22
+ describe "#google_chart_url" do
23
+ it "shows the state and event dependencies as a Google chart" do
24
+ graph = @smd.transitions.map { |t| t.to_graphviz_dot }.sort.join(";")
25
+ expect(@smd.google_chart_url).to eq("http://chart.googleapis.com/chart?cht=gv&chl=digraph{#{::CGI.escape graph}}")
26
+ end
27
+ end
28
+ end
29
+
30
+
@@ -0,0 +1,70 @@
1
+ require 'spec_helper'
2
+
3
+ describe SimpleStateMachine::Tools::Inspector do
4
+
5
+ describe "#begin_states" do
6
+ before do
7
+ @klass = Class.new(SimpleStateMachine::StateMachineDefinition) do
8
+ def add_events
9
+ define_event(:event_a, :state1 => :state2)
10
+ define_event(:event_b, :state2 => :state3)
11
+ define_event(:event_c, :state1 => :state3)
12
+ define_event(:event_c, RuntimeError => :state3)
13
+ end
14
+
15
+ def decorator_class
16
+ SimpleStateMachine::Decorator::Default
17
+ end
18
+ end
19
+ end
20
+
21
+ it "returns all 'from' states that aren't 'to' states" do
22
+ expect(@klass.new.begin_states).to eq([:state1, RuntimeError])
23
+ end
24
+ end
25
+
26
+ describe "#end_states" do
27
+ before do
28
+ @klass = Class.new(SimpleStateMachine::StateMachineDefinition) do
29
+ def add_events
30
+ define_event(:event_a, :state1 => :state2)
31
+ define_event(:event_b, :state2 => :state3)
32
+ define_event(:event_c, :state1 => :state3)
33
+ end
34
+
35
+ def decorator_class
36
+ SimpleStateMachine::Decorator::Default
37
+ end
38
+
39
+ end
40
+ end
41
+
42
+ it "returns all 'to' states that aren't 'from' states" do
43
+ expect(@klass.new.end_states).to eq([:state3])
44
+ end
45
+ end
46
+
47
+ describe "#states" do
48
+ before do
49
+ @klass = Class.new(SimpleStateMachine::StateMachineDefinition) do
50
+ def add_events
51
+ define_event(:event_a, :state1 => :state2)
52
+ define_event(:event_b, :state2 => :state3)
53
+ define_event(:event_c, :state1 => :state3)
54
+ end
55
+
56
+ def decorator_class
57
+ SimpleStateMachine::Decorator::Default
58
+ end
59
+
60
+ end
61
+ end
62
+
63
+ it "returns all states" do
64
+ expect(@klass.new.states.map(&:to_s).sort).to eq(%w{state1 state2 state3})
65
+ end
66
+ end
67
+
68
+ end
69
+
70
+
metadata CHANGED
@@ -1,176 +1,102 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: simple_state_machine
3
- version: !ruby/object:Gem::Version
4
- hash: 15
5
- prerelease:
6
- segments:
7
- - 0
8
- - 5
9
- - 2
10
- version: 0.5.2
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.6.1
11
5
  platform: ruby
12
- authors:
6
+ authors:
13
7
  - Marek de Heus
14
8
  - Petrik de Heus
15
- autorequire:
9
+ autorequire:
16
10
  bindir: bin
17
11
  cert_chain: []
18
-
19
- date: 2011-03-06 00:00:00 +01:00
20
- default_executable:
21
- dependencies:
22
- - !ruby/object:Gem::Dependency
23
- name: rake
24
- prerelease: false
25
- requirement: &id001 !ruby/object:Gem::Requirement
26
- none: false
27
- requirements:
28
- - - ">="
29
- - !ruby/object:Gem::Version
30
- hash: 3
31
- segments:
32
- - 0
33
- version: "0"
34
- type: :development
35
- version_requirements: *id001
36
- - !ruby/object:Gem::Dependency
37
- name: ZenTest
38
- prerelease: false
39
- requirement: &id002 !ruby/object:Gem::Requirement
40
- none: false
41
- requirements:
42
- - - ">="
43
- - !ruby/object:Gem::Version
44
- hash: 3
45
- segments:
46
- - 0
47
- version: "0"
48
- type: :development
49
- version_requirements: *id002
50
- - !ruby/object:Gem::Dependency
51
- name: rspec
52
- prerelease: false
53
- requirement: &id003 !ruby/object:Gem::Requirement
54
- none: false
55
- requirements:
56
- - - ">="
57
- - !ruby/object:Gem::Version
58
- hash: 3
59
- segments:
60
- - 0
61
- version: "0"
62
- type: :development
63
- version_requirements: *id003
64
- - !ruby/object:Gem::Dependency
65
- name: activerecord
66
- prerelease: false
67
- requirement: &id004 !ruby/object:Gem::Requirement
68
- none: false
69
- requirements:
70
- - - ~>
71
- - !ruby/object:Gem::Version
72
- hash: 9
73
- segments:
74
- - 2
75
- - 3
76
- - 5
77
- version: 2.3.5
78
- type: :development
79
- version_requirements: *id004
80
- - !ruby/object:Gem::Dependency
81
- name: sqlite3-ruby
82
- prerelease: false
83
- requirement: &id005 !ruby/object:Gem::Requirement
84
- none: false
85
- requirements:
86
- - - ">="
87
- - !ruby/object:Gem::Version
88
- hash: 3
89
- segments:
90
- - 0
91
- version: "0"
92
- type: :development
93
- version_requirements: *id005
94
- description: Simple State Machine is a state machine that focuses on events instead of states
95
- email:
12
+ date: 2021-12-15 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: A simple DSL to decorate existing methods with state transition guards.
15
+ email:
96
16
  - FIX@example.com
97
17
  executables: []
98
-
99
18
  extensions: []
100
-
101
- extra_rdoc_files:
19
+ extra_rdoc_files:
102
20
  - LICENSE
103
21
  - README.rdoc
104
- files:
105
- - .gitignore
106
- - .rspec
22
+ files:
23
+ - ".github/workflows/build.yml"
24
+ - ".gitignore"
25
+ - ".rspec"
26
+ - ".travis.yml"
27
+ - Changelog.rdoc
107
28
  - Gemfile
108
29
  - LICENSE
109
30
  - README.rdoc
110
31
  - Rakefile
111
- - autotest/discover.rb
112
32
  - examples/conversation.rb
113
33
  - examples/lamp.rb
114
34
  - examples/relationship.rb
115
35
  - examples/traffic_light.rb
116
36
  - examples/user.rb
37
+ - gemfiles/Gemfile.activerecord-5.2.x
38
+ - gemfiles/Gemfile.activerecord-6.0.x
39
+ - gemfiles/Gemfile.activerecord-6.1.x
40
+ - gemfiles/Gemfile.activerecord-main.x
41
+ - gemfiles/Gemfile.basic
117
42
  - lib/simple_state_machine.rb
43
+ - lib/simple_state_machine/.DS_Store
118
44
  - lib/simple_state_machine/active_record.rb
45
+ - lib/simple_state_machine/decorator/active_record.rb
46
+ - lib/simple_state_machine/decorator/default.rb
119
47
  - lib/simple_state_machine/rails2_task_loader.rb
120
48
  - lib/simple_state_machine/railtie.rb
121
49
  - lib/simple_state_machine/simple_state_machine.rb
50
+ - lib/simple_state_machine/state_machine.rb
51
+ - lib/simple_state_machine/state_machine_definition.rb
52
+ - lib/simple_state_machine/tools/graphviz.rb
53
+ - lib/simple_state_machine/tools/inspector.rb
54
+ - lib/simple_state_machine/transition.rb
122
55
  - lib/simple_state_machine/version.rb
123
- - lib/tasks/graphiz.rake
124
- - rails/graphiz.rake
56
+ - lib/tasks/graphviz.rake
125
57
  - simple_state_machine.gemspec
58
+ - spec/.DS_Store
126
59
  - spec/active_record_spec.rb
127
- - spec/decorator_spec.rb
60
+ - spec/decorator/default_spec.rb
128
61
  - spec/examples_spec.rb
129
62
  - spec/mountable_spec.rb
130
63
  - spec/simple_state_machine_spec.rb
131
64
  - spec/spec_helper.rb
132
65
  - spec/state_machine_definition_spec.rb
133
66
  - spec/state_machine_spec.rb
134
- has_rdoc: true
67
+ - spec/tools/graphviz_spec.rb
68
+ - spec/tools/inspector_spec.rb
135
69
  homepage: http://github.com/mdh/ssm
136
70
  licenses: []
137
-
138
- post_install_message:
139
- rdoc_options:
140
- - --charset=UTF-8
141
- require_paths:
71
+ metadata: {}
72
+ post_install_message:
73
+ rdoc_options:
74
+ - "--charset=UTF-8"
75
+ require_paths:
142
76
  - lib
143
- required_ruby_version: !ruby/object:Gem::Requirement
144
- none: false
145
- requirements:
77
+ required_ruby_version: !ruby/object:Gem::Requirement
78
+ requirements:
146
79
  - - ">="
147
- - !ruby/object:Gem::Version
148
- hash: 3
149
- segments:
150
- - 0
151
- version: "0"
152
- required_rubygems_version: !ruby/object:Gem::Requirement
153
- none: false
154
- requirements:
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ required_rubygems_version: !ruby/object:Gem::Requirement
83
+ requirements:
155
84
  - - ">="
156
- - !ruby/object:Gem::Version
157
- hash: 3
158
- segments:
159
- - 0
160
- version: "0"
85
+ - !ruby/object:Gem::Version
86
+ version: '0'
161
87
  requirements: []
162
-
163
- rubyforge_project:
164
- rubygems_version: 1.5.2
165
- signing_key:
166
- specification_version: 3
88
+ rubygems_version: 3.1.6
89
+ signing_key:
90
+ specification_version: 4
167
91
  summary: A simple DSL to decorate existing methods with logic that guards state transitions.
168
- test_files:
92
+ test_files:
169
93
  - spec/active_record_spec.rb
170
- - spec/decorator_spec.rb
94
+ - spec/decorator/default_spec.rb
171
95
  - spec/examples_spec.rb
172
96
  - spec/mountable_spec.rb
173
97
  - spec/simple_state_machine_spec.rb
174
98
  - spec/spec_helper.rb
175
99
  - spec/state_machine_definition_spec.rb
176
100
  - spec/state_machine_spec.rb
101
+ - spec/tools/graphviz_spec.rb
102
+ - spec/tools/inspector_spec.rb
data/autotest/discover.rb DELETED
@@ -1 +0,0 @@
1
- Autotest.add_discovery { "rspec2" }
@@ -1,13 +0,0 @@
1
- namespace :ssm do
2
- namespace :graph do
3
- desc 'Generate a url for a google chart for [class]'
4
- task :url => :environment do
5
- puts ENV['class'].constantize.state_machine_definition.google_chart_url
6
- end
7
-
8
- desc 'Opens the google chart in the browser for [class]'
9
- task :open => :environment do
10
- `open '#{::CGI.unescape(ENV['class'].constantize.state_machine_definition.google_chart_url)}'`
11
- end
12
- end
13
- end
data/rails/graphiz.rake DELETED
@@ -1,16 +0,0 @@
1
- namespace :ssm do
2
-
3
- namespace :graph do
4
-
5
- desc 'url'
6
- task 'url' do |t|
7
- end
8
-
9
- desc 'image'
10
- task 'image' do |t|
11
- end
12
-
13
- end
14
-
15
- end
16
-