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.
- data/lib/after_commit.rb +38 -27
- data/lib/after_commit/connection_adapters.rb +27 -1
- data/test/after_commit_test.rb +34 -7
- data/test/test_helper.rb +4 -0
- metadata +2 -2
data/lib/after_commit.rb
CHANGED
@@ -1,53 +1,64 @@
|
|
1
1
|
module AfterCommit
|
2
2
|
def self.record(connection, record)
|
3
|
-
|
4
|
-
|
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
|
-
|
10
|
-
|
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
|
-
|
16
|
-
|
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
|
-
|
22
|
-
|
23
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
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
|
data/test/after_commit_test.rb
CHANGED
@@ -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
|
data/test/test_helper.rb
CHANGED
@@ -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.
|
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-
|
14
|
+
date: 2009-11-21 00:00:00 +11:00
|
15
15
|
default_executable:
|
16
16
|
dependencies:
|
17
17
|
- !ruby/object:Gem::Dependency
|