state_manager 0.2.12 → 0.2.13
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/.travis.yml +3 -1
- data/Gemfile +1 -1
- data/README.md +4 -0
- data/lib/state_manager/adapters/active_record.rb +19 -11
- data/lib/state_manager/version.rb +1 -1
- data/test/adapters/active_record_test.rb +54 -21
- data/test/helper.rb +1 -1
- metadata +2 -2
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -208,6 +208,10 @@ end
|
|
208
208
|
|
209
209
|
In the above example, transitioning between 'submitted.awaiting_review' and 'submitted.reviewing' will *not* trigger the the enter/exit callbacks for the 'submitted' state, however it will be called for the two sub-states.
|
210
210
|
|
211
|
+
## ActiveRecord
|
212
|
+
|
213
|
+
StateManager works out of the box with ActiveRecord. `enter`, `entered`, `exit`, and `exited` callbacks match up to their equivalent ActiveRecord callbacks: `before_save` and `after_save`. In addition there are `enter_committed` and `exit_committed` ActiveRecord-specific callbacks that are triggered when a transtion has been committed to the underlying database. These hooks are useful for actions that are performed external to the database (e.g. enqueuing to an external task worker).
|
214
|
+
|
211
215
|
## Delayed Job Integration
|
212
216
|
|
213
217
|
StateManager comes out of the box with support for [delayed_job](https://github.com/tobi/delayed_job). If delayed_job is available, events can be defined with a `:delay` property which indicates a delay after which the event should automatically be triggered:
|
@@ -41,17 +41,12 @@ module StateManager
|
|
41
41
|
before_validation do
|
42
42
|
validate_states!
|
43
43
|
end
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
after_commit(:on => :create) { state_managers.values.map(&:after_save) }
|
51
|
-
after_commit(:on => :update) { state_managers.values.map(&:after_save) }
|
52
|
-
else # defaults to after_save
|
53
|
-
after_save { state_managers.values.map(&:after_save) }
|
54
|
-
end
|
44
|
+
|
45
|
+
# Callback hooks
|
46
|
+
after_commit(:on => :create) { state_managers.values.map(&:after_commit) }
|
47
|
+
after_commit(:on => :update) { state_managers.values.map(&:after_commit) }
|
48
|
+
before_save { state_managers.values.map(&:before_save) }
|
49
|
+
after_save { state_managers.values.map(&:after_save) }
|
55
50
|
end
|
56
51
|
end
|
57
52
|
end
|
@@ -61,6 +56,7 @@ module StateManager
|
|
61
56
|
module ManagerMethods
|
62
57
|
|
63
58
|
attr_accessor :pending_transition
|
59
|
+
attr_accessor :uncommitted_transitions
|
64
60
|
|
65
61
|
def self.included(base)
|
66
62
|
base.class_eval do
|
@@ -91,8 +87,20 @@ module StateManager
|
|
91
87
|
def after_save
|
92
88
|
return unless pending_transition
|
93
89
|
_run_after_callbacks(*pending_transition)
|
90
|
+
self.uncommitted_transitions ||= []
|
91
|
+
self.uncommitted_transitions << self.pending_transition
|
94
92
|
self.pending_transition = nil
|
95
93
|
end
|
94
|
+
|
95
|
+
def after_commit
|
96
|
+
self.uncommitted_transitions.each{ |t| run_commit_callbacks(*t) }
|
97
|
+
self.uncommitted_transitions.clear
|
98
|
+
end
|
99
|
+
|
100
|
+
def run_commit_callbacks(from_state, to_state, current_event, enter_states, exit_states)
|
101
|
+
exit_states.each{ |s| s.exit_committed if s.respond_to? :exit_committed }
|
102
|
+
enter_states.each{ |s| s.enter_committed if s.respond_to? :enter_committed }
|
103
|
+
end
|
96
104
|
|
97
105
|
def write_state(value)
|
98
106
|
resource.send :write_attribute, self.class._state_property, value.path
|
@@ -8,6 +8,7 @@ class ActiveRecordTest < Minitest::Test
|
|
8
8
|
|
9
9
|
state :unsubmitted do
|
10
10
|
event :submit, :transitions_to => 'submitted.awaiting_review'
|
11
|
+
event :activate, :transitions_to => 'active'
|
11
12
|
end
|
12
13
|
state :submitted do
|
13
14
|
state :awaiting_review do
|
@@ -25,11 +26,21 @@ class ActiveRecordTest < Minitest::Test
|
|
25
26
|
state :rejected
|
26
27
|
|
27
28
|
attr_accessor :unsubmitted_entered_count
|
29
|
+
attr_accessor :unsubmitted_enter_committed_count
|
30
|
+
attr_accessor :unsubmitted_exit_committed_count
|
31
|
+
|
28
32
|
attr_accessor :active_entered_count
|
33
|
+
attr_accessor :active_enter_committed_count
|
34
|
+
attr_accessor :active_exit_committed_count
|
35
|
+
|
29
36
|
def initialize(*args)
|
30
37
|
super
|
31
38
|
@unsubmitted_entered_count = 0
|
39
|
+
@unsubmitted_enter_committed_count = 0
|
40
|
+
@unsubmitted_exit_committed_count = 0
|
32
41
|
@active_entered_count = 0
|
42
|
+
@active_enter_committed_count = 0
|
43
|
+
@active_exit_committed_count =0
|
33
44
|
end
|
34
45
|
|
35
46
|
def will_transition(*args)
|
@@ -45,6 +56,14 @@ class ActiveRecordTest < Minitest::Test
|
|
45
56
|
def entered
|
46
57
|
state_manager.unsubmitted_entered_count += 1
|
47
58
|
end
|
59
|
+
|
60
|
+
def enter_committed
|
61
|
+
state_manager.unsubmitted_enter_committed_count += 1
|
62
|
+
end
|
63
|
+
|
64
|
+
def exit_committed
|
65
|
+
state_manager.unsubmitted_exit_committed_count += 1
|
66
|
+
end
|
48
67
|
|
49
68
|
end
|
50
69
|
|
@@ -53,6 +72,14 @@ class ActiveRecordTest < Minitest::Test
|
|
53
72
|
def entered
|
54
73
|
state_manager.active_entered_count += 1
|
55
74
|
end
|
75
|
+
|
76
|
+
def enter_committed
|
77
|
+
state_manager.active_enter_committed_count += 1
|
78
|
+
end
|
79
|
+
|
80
|
+
def exit_committed
|
81
|
+
state_manager.active_exit_committed_count += 1
|
82
|
+
end
|
56
83
|
|
57
84
|
end
|
58
85
|
|
@@ -62,12 +89,6 @@ class ActiveRecordTest < Minitest::Test
|
|
62
89
|
extend StateManager::Resource
|
63
90
|
state_manager
|
64
91
|
end
|
65
|
-
|
66
|
-
class Post2 < ActiveRecord::Base
|
67
|
-
self.table_name = 'posts'
|
68
|
-
extend StateManager::Resource
|
69
|
-
state_manager(:state, PostStates, :save_callback => :after_commit)
|
70
|
-
end
|
71
92
|
|
72
93
|
def exec(sql)
|
73
94
|
ActiveRecord::Base.connection.execute sql
|
@@ -187,8 +208,8 @@ class ActiveRecordTest < Minitest::Test
|
|
187
208
|
end
|
188
209
|
end
|
189
210
|
|
190
|
-
def
|
191
|
-
@resource =
|
211
|
+
def test_commit_callbacks
|
212
|
+
@resource = Post.find(1)
|
192
213
|
assert_state 'unsubmitted'
|
193
214
|
assert !@resource.state_manager.before_callbacks_called
|
194
215
|
assert !@resource.state_manager.after_callbacks_called
|
@@ -196,31 +217,43 @@ class ActiveRecordTest < Minitest::Test
|
|
196
217
|
@resource.transaction do
|
197
218
|
@resource.save!
|
198
219
|
assert @resource.state_manager.before_callbacks_called
|
199
|
-
assert
|
220
|
+
assert @resource.state_manager.after_callbacks_called
|
221
|
+
assert_equal @resource.state_manager.unsubmitted_enter_committed_count, 0
|
222
|
+
@resource.activate!
|
223
|
+
assert_equal @resource.state_manager.unsubmitted_exit_committed_count, 0
|
224
|
+
assert_equal @resource.state_manager.active_enter_committed_count, 0
|
200
225
|
end
|
201
|
-
|
226
|
+
assert_equal 1, @resource.state_manager.unsubmitted_enter_committed_count
|
227
|
+
assert_equal 1, @resource.state_manager.unsubmitted_exit_committed_count
|
228
|
+
assert_equal 1, @resource.state_manager.active_enter_committed_count
|
229
|
+
@resource.title = 'blah'
|
230
|
+
@resource.save!
|
231
|
+
assert_equal 1, @resource.state_manager.unsubmitted_enter_committed_count
|
232
|
+
assert_equal 1, @resource.state_manager.unsubmitted_exit_committed_count
|
233
|
+
assert_equal 1, @resource.state_manager.active_enter_committed_count
|
202
234
|
end
|
203
235
|
|
204
|
-
def
|
205
|
-
|
206
|
-
@resource =
|
236
|
+
def test_commit_callbacks_on_create
|
237
|
+
Post.transaction do
|
238
|
+
@resource = Post.new
|
207
239
|
assert !@resource.state_manager.after_callbacks_called
|
208
240
|
@resource.save
|
209
|
-
assert
|
241
|
+
assert @resource.state_manager.after_callbacks_called
|
242
|
+
assert_equal 1, @resource.state_manager.unsubmitted_entered_count
|
243
|
+
assert_equal 0, @resource.state_manager.unsubmitted_enter_committed_count
|
210
244
|
end
|
211
|
-
assert_equal @resource.state_manager.
|
212
|
-
assert @resource.state_manager.after_callbacks_called
|
245
|
+
assert_equal 1, @resource.state_manager.unsubmitted_enter_committed_count
|
213
246
|
end
|
214
247
|
|
215
|
-
def
|
216
|
-
|
217
|
-
@resource =
|
248
|
+
def test_commit_callbacks_on_different_initial_state
|
249
|
+
Post.transaction do
|
250
|
+
@resource = Post.new(:state => 'active')
|
218
251
|
assert !@resource.state_manager.after_callbacks_called
|
219
252
|
@resource.save
|
220
|
-
assert
|
253
|
+
assert @resource.state_manager.after_callbacks_called
|
221
254
|
end
|
222
255
|
assert_equal @resource.state_manager.unsubmitted_entered_count, 0
|
223
256
|
assert_equal @resource.state_manager.active_entered_count, 1
|
224
|
-
|
257
|
+
assert_equal @resource.state_manager.active_enter_committed_count, 1
|
225
258
|
end
|
226
259
|
end
|
data/test/helper.rb
CHANGED
@@ -8,6 +8,7 @@ rescue Bundler::BundlerError => e
|
|
8
8
|
exit e.status_code
|
9
9
|
end
|
10
10
|
require 'minitest/autorun'
|
11
|
+
require 'byebug'
|
11
12
|
|
12
13
|
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
13
14
|
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
@@ -15,7 +16,6 @@ require 'delayed_job_active_record'
|
|
15
16
|
require 'state_manager'
|
16
17
|
require 'timecop'
|
17
18
|
require 'database_cleaner'
|
18
|
-
require 'byebug'
|
19
19
|
|
20
20
|
DatabaseCleaner.strategy = :truncation
|
21
21
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: state_manager
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.13
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2014-06-
|
12
|
+
date: 2014-06-25 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activesupport
|