simple_state_machine 0.5.2 → 0.6.1

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.
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
-