after_commit 1.0.2 → 1.0.3

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