我有一个非常简单的方案,我正在创建一条记录,而不是附加一个文件(在save!
之后,因为我需要记录上的id来生成附件的优良名称),所有这些都包裹在其中交易。
类似的东西:
def create
activeRecord::Base.transaction do
record = A.create!(a_params)
pdf = generate_pdf
record.file.attach(
io: StringIO.new(pdf),filename: "PO##{record.id}.pdf",content_type: 'application/pdf'
)
rescue
# here it should rollback transaction on all kind of errors,if it fails upload or whatever,but it does not
raise activeRecord::Rollback
end
end
但是activestorage仅在提交发生后才上传文件,因此这种内部救援永远不会起作用,有效的方法是:
def create
record = nil
activeRecord::Base.transaction do
record = A.create!(a_params)
pdf = generate_pdf
record.file.attach(
io: StringIO.new(pdf),content_type: 'application/pdf'
)
end
rescue
record&.destroy!
end
在这里,我简化了这种情况,实际上,我有一种情况,其中一个循环创建了许多记录,并且我不想在出现任何错误的情况下保存其中的任何记录。
我发现了一些类似的问题: https://github.com/rails/rails/issues/32449 https://github.com/rails/rails/issues/31985
我如何才能以最佳方式解决此问题,我读到活动存储在后台上传文件以使交易寿命不长。因为那样会产生问题。这是有道理的,我想我也应该将pdf_generation逻辑排除在事务之外。
但是我想知道只有在生成pdf并正确上传的情况下,是否有更好的方法来创建记录。
而不是手动销毁它们并将任何其他更新还原到DB。