gpt4 book ai didi

ruby-on-rails - Rails 6 ActiveStorage 在文件上传失败时恢复事务

转载 作者:行者123 更新时间:2023-12-04 11:36:38 26 4
gpt4 key购买 nike

我有一个非常简单的场景,我正在创建一个记录,而不是附加一个文件(在 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),
filename: "PO##{record.id}.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 时创建记录。而不是手动销毁它们并在发生错误时将任何其他更新恢复到数据库。

最佳答案

我找到了一种替代方法,它仍然可以优雅地验证上传。
首先,您使用方法 ActiveStorage::Blob.create_after_upload! 上传文件, 传递一些文件参数为 io , 文件名 content_type :
https://apidock.com/rails/v6.0.0/ActiveStorage/Blob/create_after_upload%21/class
然后,您设置并保存 blob上传到附件栏。
在你的情况下,可能是这样的:

blob = ActiveStorage::Blob.create_after_upload!(
io: StringIO.new(pdf),
filename: "PO##{record.id}.pdf",
content_type: 'application/pdf')

record.file = blob
record.save!
这样,如果在文件上传到服务过程中发生任何错误,它将如最初预期的那样在当前块之前和内部引发。
注意:它是在 Rails 6.0.x 版上测试过的,所以我不知道它是否在其他版本上运行良好。

关于ruby-on-rails - Rails 6 ActiveStorage 在文件上传失败时恢复事务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59134811/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com