after_commit 1.0.2 → 1.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,53 +1,64 @@
1
1
  module AfterCommit
2
2
  def self.record(connection, record)
3
- Thread.current[:committed_records] ||= {}
4
- Thread.current[:committed_records][connection.object_id] ||= []
5
- Thread.current[:committed_records][connection.object_id] << record
3
+ prepare_collection :committed_records, connection
4
+ add_to_collection :committed_records, connection, record
6
5
  end
7
6
 
8
7
  def self.record_created(connection, record)
9
- Thread.current[:committed_records_on_create] ||= {}
10
- Thread.current[:committed_records_on_create][connection.object_id] ||= []
11
- Thread.current[:committed_records_on_create][connection.object_id] << record
8
+ prepare_collection :committed_records_on_create, connection
9
+ add_to_collection :committed_records_on_create, connection, record
12
10
  end
13
11
 
14
12
  def self.record_updated(connection, record)
15
- Thread.current[:committed_records_on_update] ||= {}
16
- Thread.current[:committed_records_on_update][connection.object_id] ||= []
17
- Thread.current[:committed_records_on_update][connection.object_id] << record
13
+ prepare_collection :committed_records_on_update, connection
14
+ add_to_collection :committed_records_on_update, connection, record
18
15
  end
19
16
 
20
17
  def self.record_destroyed(connection, record)
21
- Thread.current[:committed_records_on_destroy] ||= {}
22
- Thread.current[:committed_records_on_destroy][connection.object_id] ||= []
23
- Thread.current[:committed_records_on_destroy][connection.object_id] << record
18
+ prepare_collection :committed_records_on_destroy, connection
19
+ add_to_collection :committed_records_on_destroy, connection, record
20
+ end
21
+
22
+ def self.records(connection)
23
+ collection :committed_records, connection
24
24
  end
25
25
 
26
26
  def self.created_records(connection)
27
- Thread.current[:committed_records_on_create] ||= {}
28
- Thread.current[:committed_records_on_create][connection.object_id] ||= []
27
+ collection :committed_records_on_create, connection
29
28
  end
30
29
 
31
30
  def self.updated_records(connection)
32
- Thread.current[:committed_records_on_update] ||= {}
33
- Thread.current[:committed_records_on_update][connection.object_id] ||= []
31
+ collection :committed_records_on_update, connection
34
32
  end
35
33
 
36
34
  def self.destroyed_records(connection)
37
- Thread.current[:committed_records_on_destroy] ||= {}
38
- Thread.current[:committed_records_on_destroy][connection.object_id] ||= []
39
- end
40
-
41
- def self.records(connection)
42
- Thread.current[:committed_records] ||= {}
43
- Thread.current[:committed_records][connection.object_id] ||= []
35
+ collection :committed_records_on_destroy, connection
44
36
  end
45
37
 
46
38
  def self.cleanup(connection)
47
- Thread.current[:committed_records] = {}
48
- Thread.current[:committed_records_on_create] = {}
49
- Thread.current[:committed_records_on_update] = {}
50
- Thread.current[:committed_records_on_destroy] = {}
39
+ [
40
+ :committed_records,
41
+ :committed_records_on_create,
42
+ :committed_records_on_update,
43
+ :committed_records_on_destroy
44
+ ].each do |collection|
45
+ Thread.current[collection] ||= {}
46
+ Thread.current[collection][connection.old_transaction_key] = []
47
+ end
48
+ end
49
+
50
+ def self.prepare_collection(collection, connection)
51
+ Thread.current[collection] ||= {}
52
+ Thread.current[collection][connection.unique_transaction_key] ||= []
53
+ end
54
+
55
+ def self.add_to_collection(collection, connection, record)
56
+ Thread.current[collection][connection.unique_transaction_key] << record
57
+ end
58
+
59
+ def self.collection(collection, connection)
60
+ Thread.current[collection] ||= {}
61
+ Thread.current[collection][connection.old_transaction_key] ||= []
51
62
  end
52
63
  end
53
64
 
@@ -7,7 +7,9 @@ module AfterCommit
7
7
  # override it so that after this happens, any records that were saved
8
8
  # or destroyed within this transaction now get their after_commit
9
9
  # callback fired.
10
- def commit_db_transaction_with_callback
10
+ def commit_db_transaction_with_callback
11
+ increment_transaction_pointer
12
+ committed = false
11
13
  begin
12
14
  trigger_before_commit_callbacks
13
15
  trigger_before_commit_on_create_callbacks
@@ -15,13 +17,17 @@ module AfterCommit
15
17
  trigger_before_commit_on_destroy_callbacks
16
18
 
17
19
  commit_db_transaction_without_callback
20
+ committed = true
18
21
 
19
22
  trigger_after_commit_callbacks
20
23
  trigger_after_commit_on_create_callbacks
21
24
  trigger_after_commit_on_update_callbacks
22
25
  trigger_after_commit_on_destroy_callbacks
26
+ rescue
27
+ rollback_db_transaction unless committed
23
28
  ensure
24
29
  AfterCommit.cleanup(self)
30
+ decrement_transaction_pointer
25
31
  end
26
32
  end
27
33
  alias_method_chain :commit_db_transaction, :callback
@@ -40,6 +46,14 @@ module AfterCommit
40
46
  end
41
47
  alias_method_chain :rollback_db_transaction, :callback
42
48
 
49
+ def unique_transaction_key
50
+ [object_id, transaction_pointer]
51
+ end
52
+
53
+ def old_transaction_key
54
+ [object_id, transaction_pointer - 1]
55
+ end
56
+
43
57
  protected
44
58
 
45
59
  def trigger_before_commit_callbacks
@@ -134,6 +148,18 @@ module AfterCommit
134
148
  end
135
149
  end
136
150
  end
151
+
152
+ def transaction_pointer
153
+ Thread.current[:after_commit_pointer] ||= 0
154
+ end
155
+
156
+ def increment_transaction_pointer
157
+ Thread.current[:after_commit_pointer] += 1
158
+ end
159
+
160
+ def decrement_transaction_pointer
161
+ Thread.current[:after_commit_pointer] -= 1
162
+ end
137
163
  end
138
164
  end
139
165
  end
@@ -39,6 +39,26 @@ class MockRecord < ActiveRecord::Base
39
39
  end
40
40
  end
41
41
 
42
+ class Foo < ActiveRecord::Base
43
+ attr_reader :creating
44
+
45
+ after_commit :create_bar
46
+
47
+ private
48
+
49
+ def create_bar
50
+ @creating ||= 0
51
+ @creating += 1
52
+
53
+ raise Exception, 'looping' if @creating > 1
54
+ Bar.create
55
+ end
56
+ end
57
+
58
+ class Bar < ActiveRecord::Base
59
+ #
60
+ end
61
+
42
62
  class UnsavableRecord < ActiveRecord::Base
43
63
  attr_accessor :after_commit_called
44
64
 
@@ -65,35 +85,42 @@ class AfterCommitTest < Test::Unit::TestCase
65
85
  def test_before_commit_on_create_is_called
66
86
  assert_equal true, MockRecord.create!.before_commit_on_create_called
67
87
  end
68
-
88
+
69
89
  def test_before_commit_on_update_is_called
70
90
  record = MockRecord.create!
71
91
  record.save
72
92
  assert_equal true, record.before_commit_on_update_called
73
93
  end
74
-
94
+
75
95
  def test_before_commit_on_destroy_is_called
76
96
  assert_equal true, MockRecord.create!.destroy.before_commit_on_destroy_called
77
97
  end
78
-
98
+
79
99
  def test_after_commit_on_create_is_called
80
100
  assert_equal true, MockRecord.create!.after_commit_on_create_called
81
101
  end
82
-
102
+
83
103
  def test_after_commit_on_update_is_called
84
104
  record = MockRecord.create!
85
105
  record.save
86
106
  assert_equal true, record.after_commit_on_update_called
87
107
  end
88
-
108
+
89
109
  def test_after_commit_on_destroy_is_called
90
110
  assert_equal true, MockRecord.create!.destroy.after_commit_on_destroy_called
91
111
  end
92
-
112
+
93
113
  def test_after_commit_does_not_trigger_when_transaction_rolls_back
94
114
  record = UnsavableRecord.new
95
115
  begin; record.save; rescue; end
96
-
116
+
97
117
  assert_equal false, record.after_commit_called
98
118
  end
119
+
120
+ def test_two_transactions_are_separate
121
+ Bar.delete_all
122
+ foo = Foo.create
123
+
124
+ assert_equal 1, foo.creating
125
+ end
99
126
  end
@@ -13,8 +13,12 @@ end
13
13
  ActiveRecord::Base.establish_connection({"adapter" => "sqlite3", "database" => 'test.sqlite3'})
14
14
  begin
15
15
  ActiveRecord::Base.connection.execute("drop table mock_records");
16
+ ActiveRecord::Base.connection.execute("drop table foos");
17
+ ActiveRecord::Base.connection.execute("drop table bars");
16
18
  rescue
17
19
  end
18
20
  ActiveRecord::Base.connection.execute("create table mock_records(id int)");
21
+ ActiveRecord::Base.connection.execute("create table foos(id int)");
22
+ ActiveRecord::Base.connection.execute("create table bars(id int)");
19
23
 
20
24
  require 'after_commit'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: after_commit
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 1.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nick Muerdter
@@ -11,7 +11,7 @@ autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
13
 
14
- date: 2009-11-11 00:00:00 +11:00
14
+ date: 2009-11-21 00:00:00 +11:00
15
15
  default_executable:
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency