Rails 6 ActiveStorage 在文件上传失败时恢复事务

2024-04-15

我有一个非常简单的场景,我正在创建一条记录,然后附加一个文件(之后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/32449 https://github.com/rails/rails/issues/31985 https://github.com/rails/rails/issues/31985

我怎样才能以最好的方式解决这个问题,我读过主动存储在后台上传文件,不会使交易持续很长时间。因为否则会产生问题。这是有道理的,我认为我也应该将 pdf_ Generation 逻辑从事务中取出。

But 我想知道是否有更好的方法来仅在正确生成+上传 pdf 的情况下创建记录。而不是手动销毁它们并在发生错误时恢复对数据库的任何其他更新。


我找到了一个替代方案,仍然可以优雅地验证上传。

首先使用方法上传文件ActiveStorage::Blob.create_after_upload!,将一些文件参数传递为io, filename and 内容类型: https://apidock.com/rails/v6.0.0/ActiveStorage/Blob/create_after_upload%21/class 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 上进行了测试,所以我不知道它在其他版本上是否运行良好。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Rails 6 ActiveStorage 在文件上传失败时恢复事务 的相关文章

  • 如何在使用 Active Storage 上传之前调整图像大小(与 AWS 链接)

    我尝试将 Active Storage 与 Amazon Web Services 结合使用 而不是 Carrierwave 和 Cloudinary 使用 Carrierwave 我有一些功能可以在通过上传器控制器上传之前调整图像大小 但
  • 如何在测试环境中通过 URL 访问 ActiveStorage 对象?

    给定一个具有 ActiveStorage 附件的模型 class MyObject has one attached avatar end 在开发环境中 我能够将头像作为 StringIO 对象检索 obj MyObject new val
  • Rails:测试需要访问 Rails 环境的助手(例如 request.fullpath)

    我有一个可以访问的助手request fullpath 在孤立的辅助测试中 request不可用 我应该怎么办 我可以以某种方式嘲笑它或类似的东西吗 我正在使用最新版本的 Rails 和 RSpec 这是我的助手的样子 def item a
  • 指定的 sqlite3 gem 未加载

    虽然我对 Ruby on Rails 比较陌生 但我开发应用程序已经有一段时间了 我似乎遇到的问题是 当我创建一个新的 Rails 应用程序 本地 使用 c9 时 当我启动 apache 服务器时 我似乎收到此错误 Specified sq
  • RubyMine 不能使用 Guard 吗?

    由于某些无法解释的原因 RubyMine 会自动保存您所做的每一个更改 因此每次击键都会触发 Guard 运行您的测试 最可笑的是 显然没有办法禁用这个自动保存 功能 我只是想知道 RubyMine 似乎是 Rails 开发人员中非常流行的
  • Rails:页面加载时间很长

    我有一个 Rails 项目 我在一个控制器中遇到了非常奇怪的事情 浏览器需要大约 3 分钟来加载页面 但 Rails 在日志中写入 Completed 200 OK in 20563ms Views 17144 2ms ActiveReco
  • 抑制 Rspec 3 的回溯

    我正在使用 rspec 3 2 0 和 capybara 2 4 4 并在我的 spec helper rb 文件中如下所示 config full backtrace false 对于大多数错误 我都会得到回溯 例如 Failure Er
  • Mongoid 命名范围比较同一文档中的两个时间字段

    我需要在 Mongoid 中创建一个命名范围来比较同一文档中的两个时间字段 例如 scope foo where gt updated at gt gt checked at 这显然不会像它对待的那样起作用 checked at作为一个符号
  • MONGODB [DEBUG] 游标的cursor.refresh() 7078636577051629992

    更新大型 json 列表时 出现以下错误 2012 04 01T09 34 00 00 00 app run 1 MONGODB DEBUG cursor refresh for cursor 7078636577051629992 201
  • 渲染:带参数的动作

    我有一个有 2 种方法的类 第一个方法由视图使用一些 GET 参数 params page 调用 我想保存这些参数并通过渲染操作将它们发送到我的第二个方法 class exemple def first sql save of params
  • Rails 4 i18n,如何转换子域用于区域设置的路由

    我正在使用子域来确定 Rails 4 网站中的区域设置 我完全按照我想要的方式使用区域设置切换器 但现在我需要翻译路线 并且我不确定继续的最佳方法 我看过https github com kwi i18n routing https git
  • 如何在 Rails 3.2.1 版本中注释 Rails 模型

    我正在尝试遵循一些在线教程来在 Rails 中注释我的模型 然而 似乎所有教程都在谈论过时的注释版本或不正确的安装 这真是一团糟 到目前为止我已经尝试过以下方法 1 在 Gemfile 中添加此内容 gem annotate 2 4 0 2
  • 多态控制器和调用对象

    我的地址具有多态关系 可以由成员或依赖者拥有 一切看起来都很棒 直到我意识到除非我遗漏了一些东西 否则我不知道创建它的对象是什么类型 有没有办法告诉路由文件包含对象的类型 Models class Member lt ActiveRecor
  • Rails 注释分段错误

    有一些问题围绕着这个问题 但没有什么真正能满足我的需求 After I bundle install下面列出了我的 Gemfile 我运行annotate并出现以下错误 Users nickcoelius rvm gems ruby 1 8
  • 捆绑安装无法从 https://rubygems.org/ 获取规格

    我正在尝试遵循 Hartl Rails 教程 但在使用捆绑器 gem 时遇到了问题 使用命令 bundle install 或 bundle update 时 我得到以下输出 从中获取源索引https rubygems org https
  • 预期的 ProductField,出现数组问题

    我有一个 Rails 4 应用程序 它有一个如下所示的 params 块 def store params params require store permit name description user id products attr
  • Rails:CSRF 令牌不工作但已设置

    我在 Heroku 上有我的 Rails 3 应用程序 当我发送银行信息时 我得到 WARNING Can t verify CSRF token authenticity但我的 CSRF 令牌已设置 https gist github c
  • Rails Active Admin css 与 Twitter Bootstrap css 冲突

    我对 Rails 资产管道有点陌生 所以我可能做错了什么 我正在尝试为我的后端使用 Active Admin 为我的前端应用程序使用 twitter bootstrap css 我将 bootstrap css 添加到 应用程序 资产 样式
  • 在rails中,如何将记录作为csv文件返回

    我有一个名为 Entries 的简单数据库表 class CreateEntries lt ActiveRecord Migration def self up create table entries do t t string firs
  • 创建一个简单的 Rails 3 文本助手 Gem [重复]

    这个问题在这里已经有答案了 我一直在开发我的第一个 Rails 3 插件 以打包一个我喜欢在ApplicationHelper我所有的应用程序 你可以看到整个代码在 Github 上 https github com burlesona s

随机推荐

  • 使用 Django 的 ORM 加速批量插入?

    我计划使用 django 的 ORM 将从约 750 个文件 每个约 250MB 中获取的 10 亿条记录上传到数据库 目前每个文件需要大约 20 分钟来处理 我想知道是否有任何方法可以加速这个过程 我采取了以下措施 使用 transact
  • LINQ 语句比“foreach”循环更快吗?

    我正在编写一个网格渲染管理器 并认为将使用相同着色器的所有网格进行分组 然后在我处于该着色器通道中时渲染它们是一个好主意 我目前正在使用foreach循环 但想知道使用 LINQ 是否可以提高性能 为什么 LINQ 应该更快 它还在内部使用
  • 如何获取 ember 应用程序控制器中模板复选框的值

    我正在尝试查找控制器中是否选中了该复选框 这是我的模板 这是我的控制器 App Ember Application create App ApplicationController Ember Controller extend
  • PyQT 线程的最简单方法

    我在 PyQt 中有一个带有函数的 GUIaddImage image path 很容易想象 当需要将新图像添加到 QListWidget 中时会调用它 为了检测文件夹中的新图像 我使用threading Thread with watch
  • 如何使用 JSF 设置 HTTP 状态代码?

    我在 WebSphere Application Server 上使用 Apache Myfaces 2 2 我有一个 JSF 页面 它 测试 与文件系统和数据库的连接 当连接失败时 我想返回另一个HTTP状态代码 我怎样才能用 JSF 做
  • 按二级键对多维数组进行排序

    我有一个看起来像这样的数组 array 3 Fall Quarter 2012 gt array 2 20121018 gt array 1 agenda gt string 55 Fall 2012 Agenda 20121018 pdf
  • 无法让 ZClip 工作

    我知道它甚至在这个网站上也能工作 但只有当我通过 h1 元素触发它时 我需要通过图像 代表副本 触发它 但当我尝试时它根本不起作用 这是我的 JavaScript copyTxt click function alert Txt2Copy
  • 在 Java Card 上将 byte[] 转换为 Short[] 的快速方法

    我想在 Java 卡上优化 SHA 3 算法 我需要一种消耗更少内存的快速算法 可以轻松转换byte to short 或短 to byte 我当前的实现如下所示 private short byteToShort byte b int l
  • 表达 3.0 如何使用 app.locals.use 和 res.locals.use

    我在express3 0rc2上 如何使用app locals use 它还存在吗 和res locals use 我看到了这个https github com visionmedia express issues 1131 https g
  • 为什么 Range 有效,而 Cells 无效?

    我试图通过将一个范围内的值分配给另一个范围来将一些数据从一个工作簿移动到另一个工作簿中 当我使用正常的 Range 语法指定目标范围 Range A1 B2 时 我的代码可以工作 但是如果我尝试使用 Range Cells 语法 Range
  • 响应式视频播放器

    我需要一个使用 bootstrap 开发的响应式布局网站的视频播放器 这意味着当我重新调整屏幕大小或在不同尺寸的屏幕中查看页面时 播放器应该自动适合屏幕 我尝试过 jwplayer 和 flowplayer 但没有成功 http www l
  • 串行或并行调用多个ajax请求

    我有3个功能 load graphs national container natl rates container natl counts load graphs division Western container west rates
  • 添加 UIFont 并查找字体系列会因 EXC_BAD_ACCESS 崩溃

    我的问题是 当我添加描述的字体时here https stackoverflow com questions 3350131 how to add new font to xcode 3 2当我想检索字体系列名称时 UIFont famil
  • .NET Core 模板的 Markdown 语法是什么

    我有一个 NET Core 模板 https github com cilerler burcin blob master dist template config template json想知道如何根据设置的标志隐藏 markdown
  • XML 元素是否有标准的命名约定? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 XML 文档是否有任何标准 事实上的标准或其他标准 例如 哪种是编写标签的 最佳 方式
  • Java 中受保护的访问修饰符

    我在理解java中的受保护访问修饰符 或其背后的设计 时遇到了一些困难 我认为这意味着包访问和通过继承包含抽象成员的类的对象进行访问 我编写了以下示例代码 我发现如果未注释 注释掉的行会产生编译错误 为什么我可以通过 Second 中的 S
  • 是否可以在应用程序组件上使用 [ngClass],其中该类位于 Angular 6 的组件内部?

    我有一个 Angular 6 应用程序 我正在尝试将另一个 CSS 类应用到我的应用程序组件之一app component html文件 基本上 我想根据条件更改应用程序页脚的颜色 而所有其他情况都不显示页脚 所以 我的代码如下所示 应用程
  • 我的 Visual Studio 项目是 Web 应用程序还是网站?

    首先 什么时候使用什么以及它们之间的总体差异之前已经回答过 但我找不到这个问题的答案 在哪里可以检查我的 Visual Studio 项目是 Web 应用程序还是网站 区分网站和 Web 应用程序的最简单方法是查看项目的图标 Web Sit
  • C# IComparer 标准用法问题

    我有一个问题 这是否是在 C 中使用 IComparer 的标准 假设我有一个情况 其中有三个 Person 对象 P1 P2 和 P3 假设我调用 Compare 方法并传入 P1 和 P2 结果为 0 这本质上意味着两个人应该被归类为相
  • Rails 6 ActiveStorage 在文件上传失败时恢复事务

    我有一个非常简单的场景 我正在创建一条记录 然后附加一个文件 之后save 因为我需要记录上的 id 来生成附件的细名 所有这些都包含在事务中 就像是 def create ActiveRecord Base transaction do