ruby-on-rails 什么ActiveRecord事务不会回滚?

rsaldnfx  于 5个月前  发布在  Ruby
关注(0)|答案(1)|浏览(78)

我希望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回调中。

holgip5t

holgip5t1#

问题是事务发生在ActiveRecord回调中。由于回调本身 Package 在事务中,因此我试图执行的事务是嵌套事务。因此,引发ActiveRecord::Rollback异常会导致外部事务回滚。
根据文件:
为了获得嵌套事务的ROLLBACK,您可以通过传递requires_new:true来请求真实的子事务。如果出现任何错误,数据库将回滚到子事务的开头,而不会回滚父事务。
所以固定的例子看起来像这样:

puts "+++ Before Transaction +++"

ActiveRecord::Base.transaction(requires_new: true) do
  puts "+++ In Transaction +++"
  perform

  puts "+++ Before Rollback +++"
  raise ActiveRecord::Rollback
end

puts "+++ After Transaction +++"

字符串

相关问题