graph_mediator 0.2.1
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/.document +4 -0
- data/.gitignore +26 -0
- data/LICENSE +20 -0
- data/README.rdoc +136 -0
- data/Rakefile +32 -0
- data/graph_mediator.gemspec +31 -0
- data/lib/graph_mediator.rb +509 -0
- data/lib/graph_mediator/locking.rb +50 -0
- data/lib/graph_mediator/mediator.rb +260 -0
- data/lib/graph_mediator/version.rb +3 -0
- data/spec/database.rb +12 -0
- data/spec/examples/course_example_spec.rb +91 -0
- data/spec/examples/dingo_pen_example_spec.rb +288 -0
- data/spec/graph_mediator_spec.rb +500 -0
- data/spec/integration/changes_spec.rb +159 -0
- data/spec/integration/locking_tests_spec.rb +214 -0
- data/spec/integration/nesting_spec.rb +113 -0
- data/spec/integration/threads_spec.rb +59 -0
- data/spec/integration/validation_spec.rb +19 -0
- data/spec/investigation/alias_method_chain_spec.rb +170 -0
- data/spec/investigation/insert_subclass_spec.rb +122 -0
- data/spec/investigation/insert_superclass_spec.rb +131 -0
- data/spec/investigation/module_super_spec.rb +88 -0
- data/spec/investigation/self_decorating.rb +55 -0
- data/spec/mediator_spec.rb +201 -0
- data/spec/reservations/lodging.rb +4 -0
- data/spec/reservations/party.rb +4 -0
- data/spec/reservations/party_lodging.rb +4 -0
- data/spec/reservations/reservation.rb +18 -0
- data/spec/reservations/schema.rb +33 -0
- data/spec/spec.opts +3 -0
- data/spec/spec_helper.rb +65 -0
- metadata +173 -0
@@ -0,0 +1,159 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
|
2
|
+
|
3
|
+
describe "GraphMediator change tracking scenarios" do
|
4
|
+
|
5
|
+
before(:all) do
|
6
|
+
create_schema do |conn|
|
7
|
+
conn.create_table(:changes_roots, :force => true) do |t|
|
8
|
+
t.string :name
|
9
|
+
t.string :state
|
10
|
+
t.integer :changes_dependents_count
|
11
|
+
end
|
12
|
+
conn.create_table(:changes_dependents, :force => true) do |t|
|
13
|
+
t.string :name
|
14
|
+
t.integer :number
|
15
|
+
t.belongs_to :changes_root
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class ChangesDependent < ActiveRecord::Base
|
20
|
+
belongs_to :changes_root, :counter_cache => true
|
21
|
+
end
|
22
|
+
class ChangesRoot < ActiveRecord::Base
|
23
|
+
cattr_accessor :tests
|
24
|
+
has_many :changes_dependents
|
25
|
+
include GraphMediator
|
26
|
+
mediate :dependencies => [ChangesDependent]
|
27
|
+
mediate_reconciles :reconciles do |instance|
|
28
|
+
instance.tests.call(instance) unless instance.tests.nil?
|
29
|
+
end
|
30
|
+
def reconciles; :reconciles; end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
before(:each) do
|
35
|
+
ChangesRoot.tests = nil
|
36
|
+
@today = Date.today
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should track changes to mediated instance" do
|
40
|
+
r = ChangesRoot.new(:name => :foo)
|
41
|
+
r.save_without_mediation!
|
42
|
+
r.state = :one
|
43
|
+
changes = r.changes
|
44
|
+
run = false
|
45
|
+
r.tests = Proc.new do |instance|
|
46
|
+
instance.changes.should == {}
|
47
|
+
instance.mediated_changes.should == { ChangesRoot => { r.id => changes } }
|
48
|
+
run = true
|
49
|
+
end
|
50
|
+
r.save!
|
51
|
+
run.should be_true
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should track changes to a newly created mediated instance" do
|
55
|
+
r = ChangesRoot.new(:name => :foo)
|
56
|
+
changes = r.changes
|
57
|
+
run = false
|
58
|
+
r.tests = Proc.new do |instance|
|
59
|
+
instance.should equal(r)
|
60
|
+
instance.changes.should == {}
|
61
|
+
instance.mediated_changes.should == { ChangesRoot => { :_created => [changes] } }
|
62
|
+
run = true
|
63
|
+
end
|
64
|
+
r.save!
|
65
|
+
run.should be_true
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should track addition of a dependent" do
|
69
|
+
r = ChangesRoot.new(:name => :foo)
|
70
|
+
r.save_without_mediation!
|
71
|
+
d = r.changes_dependents.build(:name => :bar)
|
72
|
+
changes = d.changes
|
73
|
+
run = false
|
74
|
+
r.tests = Proc.new do |instance|
|
75
|
+
instance.mediated_changes.should == { ChangesDependent => { :_created => [ changes ] } }
|
76
|
+
run = true
|
77
|
+
end
|
78
|
+
d.save!
|
79
|
+
run.should be_true
|
80
|
+
end
|
81
|
+
|
82
|
+
it "should track changes to a dependent" do
|
83
|
+
r = ChangesRoot.new(:name => :foo)
|
84
|
+
r.save_without_mediation!
|
85
|
+
d = r.changes_dependents.create!(:name => :bar)
|
86
|
+
d.number = 2
|
87
|
+
changes = d.changes
|
88
|
+
run = false
|
89
|
+
r.tests = Proc.new do |instance|
|
90
|
+
instance.mediated_changes.should == { ChangesDependent => { d.id => changes } }
|
91
|
+
run = true
|
92
|
+
end
|
93
|
+
d.save!
|
94
|
+
run.should be_true
|
95
|
+
end
|
96
|
+
|
97
|
+
it "should track deletion of a dependent" do
|
98
|
+
r = ChangesRoot.new(:name => :foo)
|
99
|
+
r.save_without_mediation!
|
100
|
+
d = r.changes_dependents.create!(:name => :bar)
|
101
|
+
run = false
|
102
|
+
r.tests = Proc.new do |instance|
|
103
|
+
instance.mediated_changes.should == { ChangesDependent => { :_destroyed => [d.id] } }
|
104
|
+
run = true
|
105
|
+
end
|
106
|
+
d.destroy
|
107
|
+
run.should be_true
|
108
|
+
end
|
109
|
+
|
110
|
+
it "should differentiate changes to attributes with the same name in different classes." do
|
111
|
+
r = ChangesRoot.new(:name => :foo)
|
112
|
+
r.save_without_mediation!
|
113
|
+
d = r.changes_dependents.create!(:name => :bar)
|
114
|
+
|
115
|
+
d.number = 3
|
116
|
+
dep_changes = d.changes
|
117
|
+
r.name = 'different'
|
118
|
+
root_changes = r.changes
|
119
|
+
run = false
|
120
|
+
mediated_changes = nil
|
121
|
+
r.tests = Proc.new do |instance|
|
122
|
+
d.save!
|
123
|
+
mediated_changes = instance.mediated_changes
|
124
|
+
mediated_changes.should == { ChangesRoot => { r.id => root_changes }, ChangesDependent => { d.id => dep_changes } }
|
125
|
+
run = true
|
126
|
+
end
|
127
|
+
r.save!
|
128
|
+
run.should be_true
|
129
|
+
mediated_changes.changed_name?.should be_true
|
130
|
+
mediated_changes.attribute_changed?(:name, ChangesDependent).should be_false
|
131
|
+
mediated_changes.changes_dependent_changed_name?.should be_false
|
132
|
+
mediated_changes.changes_root_changed_name?.should be_true
|
133
|
+
|
134
|
+
r.state = :new_state
|
135
|
+
root_changes = r.changes
|
136
|
+
d.name = 'also different'
|
137
|
+
dep_changes = d.changes
|
138
|
+
r.save!
|
139
|
+
run.should be_true
|
140
|
+
mediated_changes.changed_name?.should be_true
|
141
|
+
mediated_changes.changes_dependent_changed_name?.should be_true
|
142
|
+
mediated_changes.changes_root_changed_name?.should be_false
|
143
|
+
end
|
144
|
+
|
145
|
+
it "should handle attribute queries for classes that have had no changes recorded" do
|
146
|
+
r = ChangesRoot.new(:name => :foo)
|
147
|
+
r.save_without_mediation!
|
148
|
+
run = false
|
149
|
+
r.tests = Proc.new do |instance|
|
150
|
+
mediated_changes = instance.mediated_changes
|
151
|
+
mediated_changes.should == { ChangesRoot => { r.id => {} }}
|
152
|
+
mediated_changes.changes_dependent_changed_name?.should be_false
|
153
|
+
run = true
|
154
|
+
end
|
155
|
+
r.save!
|
156
|
+
run.should be_true
|
157
|
+
end
|
158
|
+
|
159
|
+
end
|
@@ -0,0 +1,214 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
|
2
|
+
|
3
|
+
require 'reservations/party_lodging'
|
4
|
+
require 'reservations/lodging'
|
5
|
+
require 'reservations/party'
|
6
|
+
require 'reservations/reservation'
|
7
|
+
|
8
|
+
describe "GraphMediator locking scenarios" do
|
9
|
+
|
10
|
+
before(:all) do
|
11
|
+
load 'reservations/schema.rb'
|
12
|
+
end
|
13
|
+
|
14
|
+
before(:each) do
|
15
|
+
@today = Date.today
|
16
|
+
@handle1_r1 = Reservation.create!(:starts => @today, :ends => @today + 1, :name => 'foo')
|
17
|
+
@handle2_r1 = Reservation.find(@handle1_r1.id)
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should be possible to create an unattached dependent object" do
|
21
|
+
Lodging.create!.should_not be_nil
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should increment lock_version for save_without_mediation" do
|
25
|
+
lambda {
|
26
|
+
@handle1_r1.starts = @today - 1
|
27
|
+
@handle1_r1.save_without_mediation
|
28
|
+
}.should change(@handle1_r1, :lock_version).by(1)
|
29
|
+
end
|
30
|
+
|
31
|
+
context "with optimistic locking for the graph" do
|
32
|
+
|
33
|
+
it "should raise Stale for conflicts updating root" do
|
34
|
+
@handle2_r1.update_attributes(:name => 'bar')
|
35
|
+
lambda { @handle1_r1.update_attributes(:name => 'baz') }.should raise_error(ActiveRecord::StaleObjectError)
|
36
|
+
@handle1_r1.reload
|
37
|
+
@handle1_r1.name.should == 'bar'
|
38
|
+
end
|
39
|
+
|
40
|
+
# Creating root cannot conflict
|
41
|
+
# because the rows do not exist until the mediation transaction completes
|
42
|
+
# so no one else is in a position to write first
|
43
|
+
|
44
|
+
# not possible? ActiveRecord::Locking::Optimistic does not decorate :destroy
|
45
|
+
# it "should raise stale for conflicts deleting root" do
|
46
|
+
|
47
|
+
it "should raise Stale for conflicts creating children" do
|
48
|
+
@handle2_r1.parties.create(:name => 'Bob')
|
49
|
+
lambda { @handle1_r1.update_attributes(:name => 'baz') }.should raise_error(ActiveRecord::StaleObjectError)
|
50
|
+
end
|
51
|
+
|
52
|
+
context "with children" do
|
53
|
+
|
54
|
+
before(:each) do
|
55
|
+
@handle1_r1.mediated_transaction do
|
56
|
+
@party1 = @handle1_r1.parties.create(:name => 'Bob')
|
57
|
+
@party2 = @handle1_r1.parties.create(:name => 'Joe')
|
58
|
+
@room1 = @handle1_r1.lodgings.create(:room_number => 1)
|
59
|
+
@room2 = @handle1_r1.lodgings.create(:room_number => 2)
|
60
|
+
end
|
61
|
+
@handle2_r1.reload
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should raise Stale for conflicts updating children and root" do
|
65
|
+
@handle2_r1.parties.first.update_attributes(:name => 'Frank')
|
66
|
+
lambda { @handle1_r1.update_attributes(:name => 'baz') }.should raise_error(ActiveRecord::StaleObjectError)
|
67
|
+
end
|
68
|
+
|
69
|
+
it "should raise Stale for conflicts updating just children" do
|
70
|
+
@handle2_r1.parties.first.update_attributes(:name => 'Frank')
|
71
|
+
# version has incremented because of update to party, so, :versioning touch fails
|
72
|
+
lambda { @handle1_r1.mediated_transaction {} }.should raise_error(ActiveRecord::StaleObjectError)
|
73
|
+
end
|
74
|
+
|
75
|
+
it "should raise Stale for conflicts deleting children and touching root" do
|
76
|
+
@handle2_r1.parties.first.destroy
|
77
|
+
lambda { @handle1_r1.update_attributes(:name => 'baz') }.should raise_error(ActiveRecord::StaleObjectError)
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should not raise stale because of updates to its own children counter_caches" do
|
81
|
+
@handle1_r1.mediated_transaction do
|
82
|
+
@handle1_r1.lodge(@party1, :in => @room1)
|
83
|
+
@handle1_r1.parties.first.touch
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
it "should increment lock_version for the graph if a dependent is changed" do
|
88
|
+
lambda {
|
89
|
+
@handle1_r1.parties.first.touch
|
90
|
+
@handle1_r1.reload
|
91
|
+
}.should change(@handle1_r1, :lock_version).by(1)
|
92
|
+
end
|
93
|
+
|
94
|
+
context "with lock_version for dependent children" do
|
95
|
+
|
96
|
+
before(:all) do
|
97
|
+
create_schema do |conn|
|
98
|
+
conn.add_column(:parties, :lock_version, :integer)
|
99
|
+
end
|
100
|
+
Party.reset_column_information
|
101
|
+
end
|
102
|
+
|
103
|
+
after(:all) do
|
104
|
+
create_schema do |conn|
|
105
|
+
conn.remove_column(:parties, :lock_version)
|
106
|
+
end
|
107
|
+
Party.reset_column_information
|
108
|
+
end
|
109
|
+
|
110
|
+
it "will raise stale because of updates to its own children counter_caches" do
|
111
|
+
# Reservation::MediatorProxy._graph_mediator_logger = TestLogger.new
|
112
|
+
Reservation::MediatorProxy._graph_mediator_log_level = 0
|
113
|
+
r = Reservation.create!(:starts => @today, :ends => @today)
|
114
|
+
party, room = nil, nil
|
115
|
+
r.mediated_transaction do
|
116
|
+
party = r.parties.create(:name => 'Joe')
|
117
|
+
room = r.lodgings.create(:room_number => 1)
|
118
|
+
end
|
119
|
+
r.mediated_transaction do
|
120
|
+
r.lodge(party, :in => room)
|
121
|
+
lambda { party.touch }.should raise_error(ActiveRecord::StaleObjectError)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
context "within a mediated transaction" do
|
129
|
+
|
130
|
+
it "should not raise stale for changes made within a mediated transaction" do
|
131
|
+
lambda { @handle1_r1.mediated_transaction do
|
132
|
+
@handle1_r1.parties.create(:name => 'Bob')
|
133
|
+
end }. should change(@handle1_r1, :lock_version).by(1)
|
134
|
+
end
|
135
|
+
|
136
|
+
it "should not raise stale for counter_caches within a mediated transaction" do
|
137
|
+
lambda { @handle1_r1.mediated_transaction do
|
138
|
+
@handle1_r1.parties.create(:name => 'Bob')
|
139
|
+
@handle1_r1.update_attributes(:name => 'baz')
|
140
|
+
end }.should change(@handle1_r1, :lock_version).by(1)
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
end
|
146
|
+
|
147
|
+
module GraphMediatorLocking # namespace to prevent helper class conflicts
|
148
|
+
|
149
|
+
describe "GraphMediator locking scenarios for classes without counter_caches" do
|
150
|
+
|
151
|
+
before(:all) do
|
152
|
+
create_schema do |connection|
|
153
|
+
connection.create_table(:foos, :force => true) do |t|
|
154
|
+
t.string :name
|
155
|
+
t.integer :lock_version, :default => 0
|
156
|
+
t.timestamps
|
157
|
+
end
|
158
|
+
|
159
|
+
connection.create_table(:bars, :force => true) do |t|
|
160
|
+
t.string :name
|
161
|
+
t.belongs_to :foo
|
162
|
+
t.timestamps
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
class Bar < ActiveRecord::Base
|
168
|
+
belongs_to :foo
|
169
|
+
end
|
170
|
+
|
171
|
+
class Foo < ActiveRecord::Base
|
172
|
+
include GraphMediator
|
173
|
+
mediate :dependencies => Bar
|
174
|
+
has_many :bars
|
175
|
+
end
|
176
|
+
|
177
|
+
before(:each) do
|
178
|
+
@h1_foo1 = Foo.create(:name => 'one')
|
179
|
+
@h2_foo1 = Foo.find(@h1_foo1.id)
|
180
|
+
end
|
181
|
+
|
182
|
+
it "should also raise Stale for conflicts updating root" do
|
183
|
+
# nothing to touch...
|
184
|
+
@h2_foo1.update_attributes(:name => 'bar')
|
185
|
+
lambda { @h1_foo1.update_attributes(:name => 'baz') }.should raise_error(ActiveRecord::StaleObjectError)
|
186
|
+
@h1_foo1.reload
|
187
|
+
@h1_foo1.name.should == 'bar'
|
188
|
+
end
|
189
|
+
|
190
|
+
it "should raise Stale for conflicts deleting children and touching root" do
|
191
|
+
@h1_foo1.bars << Bar.create!
|
192
|
+
@h2_foo1.bars.first.destroy
|
193
|
+
lambda { @h1_foo1.update_attributes(:name => 'baz') }.should raise_error(ActiveRecord::StaleObjectError)
|
194
|
+
end
|
195
|
+
|
196
|
+
it "should increment lock_version for the graph if a dependent is added" do
|
197
|
+
lambda {
|
198
|
+
@h1_foo1.bars << Bar.create!
|
199
|
+
@h1_foo1.reload
|
200
|
+
}.should change(@h1_foo1, :lock_version).by(1)
|
201
|
+
end
|
202
|
+
|
203
|
+
it "should increment lock_version for the graph if a dependent is deleted" do
|
204
|
+
@h1_foo1.bars << Bar.create!
|
205
|
+
@h1_foo1.reload
|
206
|
+
lambda {
|
207
|
+
@h1_foo1.bars.first.destroy
|
208
|
+
@h1_foo1.reload
|
209
|
+
}.should change(@h1_foo1, :lock_version).by(1)
|
210
|
+
end
|
211
|
+
|
212
|
+
end
|
213
|
+
|
214
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
|
2
|
+
|
3
|
+
describe "Nesting of mediated_transactions" do
|
4
|
+
|
5
|
+
before(:all) do
|
6
|
+
#@old_logger = GraphMediator::Configuration.logger
|
7
|
+
#GraphMediator::Configuration.logger = TestLogger.new
|
8
|
+
@old_log_level = GraphMediator::Configuration.log_level
|
9
|
+
GraphMediator::Configuration.log_level = ActiveSupport::BufferedLogger::DEBUG
|
10
|
+
end
|
11
|
+
|
12
|
+
after(:all) do
|
13
|
+
#GraphMediator::Configuration.logger = @old_logger
|
14
|
+
GraphMediator::Configuration.log_level = @old_log_level
|
15
|
+
end
|
16
|
+
|
17
|
+
before(:each) do
|
18
|
+
load_traceable_callback_tester
|
19
|
+
@t = Traceable.new(:name => :gizmo)
|
20
|
+
@t.save_without_mediation!
|
21
|
+
end
|
22
|
+
|
23
|
+
after(:each) do
|
24
|
+
Object.__send__(:remove_const, :Traceable)
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should only perform a single after_mediation even with nested mediated_transactions" do
|
28
|
+
@t.mediated_transaction do
|
29
|
+
@t.mediated_transaction {}
|
30
|
+
end
|
31
|
+
@traceables_callbacks.should == [:before, :reconcile, :cache]
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should only perform a single after_mediation even with implicitly nested mediated transactions" do
|
35
|
+
|
36
|
+
@t.mediated_transaction do
|
37
|
+
@t.update_attributes(:name => 'foo')
|
38
|
+
end
|
39
|
+
@traceables_callbacks.should == [:before, :reconcile, :cache]
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should handle deeper nesting" do
|
43
|
+
@t.mediated_transaction do
|
44
|
+
@t.mediated_transaction do
|
45
|
+
@t.update_attributes(:name => 'foo')
|
46
|
+
end
|
47
|
+
end
|
48
|
+
@t.__send__(:current_mediator).should be_nil
|
49
|
+
@traceables_callbacks.should == [:before, :reconcile, :cache]
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should handle errors raised while deeply nested" do
|
53
|
+
lambda { @t.mediated_transaction do
|
54
|
+
@t.mediated_transaction do
|
55
|
+
@t.mediated_transaction { raise }
|
56
|
+
end
|
57
|
+
end }.should raise_error(RuntimeError)
|
58
|
+
@t.__send__(:current_mediator).should be_nil
|
59
|
+
@traceables_callbacks.should == [:before]
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should handle errors raised and recovered while deeply nested" do
|
63
|
+
@t.mediated_transaction do
|
64
|
+
@t.mediated_transaction do
|
65
|
+
lambda { @t.mediated_transaction { raise } }.should raise_error(RuntimeError)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
@t.__send__(:current_mediator).should be_nil
|
69
|
+
@traceables_callbacks.should == [:before, :reconcile, :cache]
|
70
|
+
end
|
71
|
+
|
72
|
+
it "should call after_mediation only once even if mediated_transaction is called on a new instance" do
|
73
|
+
Traceable.logger.debug "\n\n\nnew test"
|
74
|
+
new_t = Traceable.new(:name => 'new')
|
75
|
+
new_t.mediated_transaction { new_t.save }
|
76
|
+
@traceables_callbacks.should == [:before, :reconcile, :cache]
|
77
|
+
end
|
78
|
+
|
79
|
+
it "should clear mediator if unrecovered error raised in nested transaction" do
|
80
|
+
lambda { @t.mediated_transaction do
|
81
|
+
@t.mediated_transaction { raise }
|
82
|
+
end }.should raise_error(RuntimeError)
|
83
|
+
@t.__send__(:current_mediator).should be_nil
|
84
|
+
@traceables_callbacks.should == [:before]
|
85
|
+
end
|
86
|
+
|
87
|
+
it "should finish mediation if error raised and recovered in nested transaction" do
|
88
|
+
@t.mediated_transaction do
|
89
|
+
lambda { @t.mediated_transaction { raise } }.should raise_error(RuntimeError)
|
90
|
+
end
|
91
|
+
@t.__send__(:current_mediator).should be_nil
|
92
|
+
@traceables_callbacks.should == [:before, :reconcile, :cache]
|
93
|
+
end
|
94
|
+
|
95
|
+
it "should run no callbacks if disabled, regardless of nesting" do
|
96
|
+
@t.disable_mediation!
|
97
|
+
@t.mediated_transaction do
|
98
|
+
@t.mediated_transaction { }
|
99
|
+
end
|
100
|
+
@traceables_callbacks.should == []
|
101
|
+
end
|
102
|
+
|
103
|
+
it "should continue to be disabled if error raised and recovered in a nested transaction when mediation is disabled" do
|
104
|
+
@t.disable_mediation!
|
105
|
+
@t.mediated_transaction do
|
106
|
+
lambda { @t.mediated_transaction { raise } }.should raise_error(RuntimeError)
|
107
|
+
end
|
108
|
+
@t.__send__(:current_mediator).should be_nil
|
109
|
+
@traceables_callbacks.should == []
|
110
|
+
end
|
111
|
+
|
112
|
+
|
113
|
+
end
|