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