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 CHANGED
@@ -1,5 +1,7 @@
1
1
  rvm:
2
2
  - 1.9.3
3
+ - 2.0.0
4
+ - 2.1.0
3
5
  before_install:
4
6
  - gem install bundler --version '>= 1.2.2'
5
- script: "bundle exec rake test"
7
+ script: "bundle exec rake test"
data/Gemfile CHANGED
@@ -3,11 +3,11 @@ source "http://rubygems.org"
3
3
  gemspec
4
4
 
5
5
  group :development do
6
+ gem 'byebug'
6
7
  gem "bundler"
7
8
  gem 'delayed_job_active_record'
8
9
  gem 'activerecord'
9
10
  gem 'sqlite3'
10
11
  gem 'timecop'
11
12
  gem 'database_cleaner'
12
- gem 'byebug'
13
13
  end
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
- before_save do
45
- state_managers.values.map(&:before_save)
46
- end
47
-
48
- save_callback = options[:save_callback] && options[:save_callback].to_sym
49
- if save_callback == :after_commit
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
@@ -1,3 +1,3 @@
1
1
  module StateManager
2
- VERSION = "0.2.12"
2
+ VERSION = "0.2.13"
3
3
  end
@@ -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 test_after_commit_callback
191
- @resource = Post2.find(1)
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 !@resource.state_manager.after_callbacks_called
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
- assert @resource.state_manager.after_callbacks_called
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 test_after_commit_callback_on_create
205
- Post2.transaction do
206
- @resource = Post2.new
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 !@resource.state_manager.after_callbacks_called
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.unsubmitted_entered_count, 1
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 test_after_commit_callback_on_different_initial_state
216
- Post2.transaction do
217
- @resource = Post2.new(:state => 'active')
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 !@resource.state_manager.after_callbacks_called
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
- assert @resource.state_manager.after_callbacks_called
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.12
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-16 00:00:00.000000000 Z
12
+ date: 2014-06-25 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport