simple_state_machine 0.3.4 → 0.4.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 CHANGED
@@ -36,6 +36,14 @@ This will prevent the state from being changed.
36
36
  end
37
37
  end
38
38
 
39
+ === Example usage with exceptions
40
+ You can rescue exceptions and specify the failure state
41
+
42
+ def download_data
43
+ Service.download_data
44
+ end
45
+ event :download_data, :pending => :downloaded,
46
+ Service::ConnectionError => :download_failed
39
47
 
40
48
  == More complete implementation
41
49
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.4
1
+ 0.4.0
@@ -49,7 +49,7 @@ module SimpleStateMachine
49
49
  end
50
50
 
51
51
  def add_transition event_name, from, to
52
- transition = Transition.new(event_name.to_s, from.to_s, to.to_s)
52
+ transition = Transition.new(event_name, from, to)
53
53
  transitions << transition
54
54
  transition
55
55
  end
@@ -67,17 +67,32 @@ module SimpleStateMachine
67
67
  @subject = subject
68
68
  end
69
69
 
70
- # returns the next state for the subject for event_name
70
+ # Returns the next state for the subject for event_name
71
71
  def next_state(event_name)
72
- transition = transitions.select{|t| t.event_name.to_s == event_name.to_s && @subject.send(state_method).to_s == t.from.to_s}.first
72
+ transition = transitions.select{|t| t.is_transition_for?(event_name) && @subject.send(state_method).to_s == t.from.to_s}.first
73
73
  transition ? transition.to : nil
74
74
  end
75
75
 
76
- # transitions to the next state if next_state exists
77
- # calls illegal_event_callback event_name if no next_state is found
76
+ # Returns the error state for the subject for event_name and error
77
+ def error_state(event_name, error)
78
+ transition = transitions.select{|t| t.is_error_transition_for?(event_name, error) }.first
79
+ transition ? transition.to : nil
80
+ end
81
+
82
+ # Transitions to the next state if next_state exists.
83
+ # Calls illegal_event_callback event_name if no next_state is found
78
84
  def transition(event_name)
79
85
  if to = next_state(event_name)
80
- result = yield
86
+ begin
87
+ result = yield
88
+ rescue => e
89
+ if error_state = error_state(event_name, e)
90
+ @subject.send("#{state_method}=", error_state)
91
+ return result
92
+ else
93
+ raise
94
+ end
95
+ end
81
96
  # TODO refactor out to AR module
82
97
  if defined?(::ActiveRecord) && @subject.is_a?(::ActiveRecord::Base)
83
98
  if @subject.errors.entries.empty?
@@ -116,7 +131,21 @@ module SimpleStateMachine
116
131
 
117
132
  end
118
133
 
119
- class Transition < Struct.new(:event_name, :from, :to)
134
+ class Transition
135
+ attr_reader :event_name, :from, :to
136
+ def initialize(event_name, from, to)
137
+ @event_name = event_name.to_s
138
+ @from = from.is_a?(Class) ? from : from.to_s
139
+ @to = to.to_s
140
+ end
141
+
142
+ def is_transition_for?(event_name)
143
+ self.event_name == event_name.to_s
144
+ end
145
+
146
+ def is_error_transition_for?(event_name, error)
147
+ is_transition_for?(event_name) && error.class == from
148
+ end
120
149
  end
121
150
 
122
151
  ##
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{simple_state_machine}
8
- s.version = "0.3.4"
8
+ s.version = "0.4.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Marek de Heus", "Petrik de Heus"]
12
- s.date = %q{2010-09-04}
12
+ s.date = %q{2010-09-06}
13
13
  s.description = %q{A simple DSL to decorate existing methods with logic that guards state transitions.}
14
14
  s.email = ["FIX@example.com"]
15
15
  s.extra_rdoc_files = [
@@ -42,6 +42,20 @@ describe SimpleStateMachine do
42
42
  example.should be_state2
43
43
  end
44
44
 
45
+ it "changes state to error_state when error should be caught" do
46
+ class_with_error = Class.new(SimpleExample)
47
+ class_with_error.instance_eval do
48
+ define_method :raise_error do
49
+ raise
50
+ end
51
+ event :raise_error, :state1 => :state2, RuntimeError => :failed
52
+ end
53
+ example = class_with_error.new
54
+ example.should be_state1
55
+ example.raise_error
56
+ example.should be_failed
57
+ end
58
+
45
59
  it "raise an error if an invalid state_transition is called" do
46
60
  example = SimpleExample.new
47
61
  lambda { example.event2 }.should raise_error(SimpleStateMachine::Error, "You cannot 'event2' when state is 'state1'")
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: simple_state_machine
3
3
  version: !ruby/object:Gem::Version
4
- hash: 27
4
+ hash: 15
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
- - 3
9
8
  - 4
10
- version: 0.3.4
9
+ - 0
10
+ version: 0.4.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Marek de Heus
@@ -16,7 +16,7 @@ autorequire:
16
16
  bindir: bin
17
17
  cert_chain: []
18
18
 
19
- date: 2010-09-04 00:00:00 +02:00
19
+ date: 2010-09-06 00:00:00 +02:00
20
20
  default_executable:
21
21
  dependencies:
22
22
  - !ruby/object:Gem::Dependency