graph_mediator 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|