state_manager 0.2.12 → 0.2.13
Sign up to get free protection for your applications and to get access to all the features.
- 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
|