Skip to content

Commit 8f31175

Browse files
committed
added nested transaction rollback handling and updated specs
1 parent 83dfc58 commit 8f31175

3 files changed

Lines changed: 46 additions & 10 deletions

File tree

lib/active_graph/transaction.rb

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
module ActiveGraph
22
module Transaction
33
def rollback
4-
fail ActiveGraph::Rollback
4+
@rolled_back = true
5+
end
6+
7+
def check_rollback
8+
fail ActiveGraph::Rollback if @rolled_back
59
end
610

711
def after_commit(&block)

lib/active_graph/transactions.rb

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -42,24 +42,27 @@ def send_transaction(method, **config, &block)
4242
end
4343
end
4444

45-
def run_transaction_work(session, method, **config, &block)
46-
implicit = config.delete(:implicit)
45+
def run_transaction_work(session, method, implicit: false, **config, &block)
46+
result = nil
4747
session.send(method, **config) do |tx|
4848
self.tx = tx
49-
block.call(tx).tap do |result|
50-
if implicit &&
51-
[Core::Result, ActiveGraph::Node::Query::QueryProxy, ActiveGraph::Core::Query]
52-
.any?(&result.method(:is_a?))
53-
result.store
54-
end
49+
(result = block.call(tx)).tap do
50+
store(it) if implicit
51+
tx.check_rollback
5552
end
5653
end.tap { tx.apply_callbacks }
5754
rescue ActiveGraph::Rollback
5855
# rollbacks are silently swallowed
59-
false # to satisfy save and update conventions
56+
result
6057
ensure
6158
self.tx = nil
6259
end
60+
61+
def store(result)
62+
if [Core::Result, ActiveGraph::Node::Query::QueryProxy, ActiveGraph::Core::Query].any?(&result.method(:is_a?))
63+
result.store
64+
end
65+
end
6366
end
6467
end
6568
end

spec/active_graph/transactions_spec.rb

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,4 +122,33 @@
122122
end
123123
end
124124
end
125+
126+
describe 'rollback in nested transaction' do
127+
it 'returns the result from the inner transaction when rollback is called' do
128+
inner_result = nil
129+
ActiveGraph::Base.transaction do
130+
inner_result = ActiveGraph::Base.transaction do |tx|
131+
tx.rollback
132+
'inner result'
133+
end
134+
end
135+
expect(inner_result).to eq 'inner result'
136+
end
137+
138+
it 'allows reading model errors after failed update inside an outer transaction' do
139+
stub_node_class('ValidatedStudent') do
140+
property :name
141+
validates :name, presence: true
142+
end
143+
144+
student = ValidatedStudent.create!(name: 'Alice')
145+
146+
errors = ActiveGraph::Base.transaction do
147+
student.update(name: nil)
148+
student.errors.full_messages
149+
end
150+
151+
expect(errors).to include("Name can't be blank")
152+
end
153+
end
125154
end

0 commit comments

Comments
 (0)