Bubbling Up Nested-transaction Failures с ActiveRecord
У меня есть метод в объекте службы, который объединяет операции, которые должны быть заключены в транзакцию. Некоторые из этих операций также заключены в транзакции. Например:
class PostCreator
def create
ActiveRecord::Base.transaction do
post.do_this
post.do_that
user.do_more(post, other_stuff)
end
end
end
def Post
def do_this
transaction do; ...; end
end
end
Мне нужно, чтобы все вложенные отказы всплывали до самого верха, но я не уверен, как это сделать, и ActiveRecord docs на вложенных транзакциях похоже, не предлагают решения. Из документов:
# Standard nesting
User.transaction do
User.create(username: 'Kotori')
User.transaction do
User.create(username: 'Nemu')
raise ActiveRecord::Rollback # This won't bubble up:
# _Both_ users will still be created.
end
end
# Nesting with `requires_new: true` on the nested transaction
User.transaction do
User.create(username: 'Kotori')
User.transaction(requires_new: true) do
User.create(username: 'Nemu')
raise ActiveRecord::Rollback # This won't bubble up either
# "Kotori" will still be created.
end
end
Ответы
Ответ 1
Здесь вы можете получить ошибки в своих вложенных транзакциях:
User.transaction do
User.create(username: 'Kotori')
raise ActiveRecord::Rollback unless User.transaction(requires_new: true) do
User.create(username: 'Nemu')
raise ActiveRecord::Rollback
end
end
В принципе, вы должны поднять ошибку в транзакции на верхнем уровне, чтобы она тоже откатилась. Для этого вы вызываете ошибку, если вложенная транзакция возвращает значение false (nil) или правное значение.
Надеюсь, что это поможет!
Ответ 2
Еще один простой подход, вы можете поднять CustomError < Стандартная ошибка. В отличие от ActiveRecord:: Rollback, ошибка будет всплывать через родительские транзакции. Вы можете обращаться с ним везде, где это необходимо. Все остальные внутренние транзакции будут отменены.
Попробуйте шаблон ниже.
ActiveRecord::Base.transacton do
ActiveRecord::Base.transacton do
raise StandardError.new
end
end
Ответ 3
Бросок пользовательской ошибки всегда является хорошим вариантом в случае вложенных транзакций. Подробнее см. nested-transations-in-rails.