我希望ActiveRecord事务故意失败。问题是当我引发ActiveRecord::Rollback异常(或任何其他异常)时,回滚不会发生。在下面的代码中,perfom
方法导入一个文件。为了简单起见,让我们假设它只是更新一条记录:
puts "+++ Before Transaction +++"
ActiveRecord::Base.transaction do
puts "+++ In Transaction +++"
perform
puts "+++ Before Rollback +++"
raise ActiveRecord::Rollback
end
puts "+++ After Transaction +++"
字符串
当代码运行时,这里是服务器的输出:
+++ Before Transaction +++
+++ In Transaction +++
TRANSACTION (0.1ms) BEGIN
↳ app/models/import.rb:103:in `file_content'
Disk Storage (0.1ms) Downloaded file from key: abcdefg
Car Load (0.2ms) SELECT "cars".* FROM "cars" WHERE "cars"."make" = '207' LIMIT 1
↳ app/models/application_record.rb:82:in `try_update_or_create_report'
Car Exists? (0.3ms) SELECT 1 AS one FROM "rolling_shutters_automatism_prices" WHERE
"cars"."make" = '207' AND "cars"."id" != 5 LIMIT 1
↳ app/models/application_record.rb:106:in `try_update_report'
Car Update (0.2ms) UPDATE "cars" SET "price" = 20.0, "updated_at" = '2023-12-26 15:17:47.978023' WHERE "cars"."id" = 5
↳ app/models/application_record.rb:106:in `try_update_report'
+++ Before Rollback +++
+++ After Transaction +++
型
我期望的行为是在最后两行之间登录ROLLBACK
,但没有任何记录。为什么会这样?
我使用Rails 7.0.4和PostGres 15以及Ruby 3.2.2
编辑:我遗漏了一条重要的信息,事务发生在ActiveRecord回调中。
1条答案
按热度按时间holgip5t1#
问题是事务发生在ActiveRecord回调中。由于回调本身 Package 在事务中,因此我试图执行的事务是嵌套事务。因此,引发ActiveRecord::Rollback异常会导致外部事务回滚。
根据文件:
为了获得嵌套事务的ROLLBACK,您可以通过传递requires_new:true来请求真实的子事务。如果出现任何错误,数据库将回滚到子事务的开头,而不会回滚父事务。
所以固定的例子看起来像这样:
字符串