在 Rails 6 中使用 activestorage 时,如何在重新显示表单时保留文件?

Posted

技术标签:

【中文标题】在 Rails 6 中使用 activestorage 时,如何在重新显示表单时保留文件?【英文标题】:When using activestorage in Rails 6, how do I retain a file when redisplaying a form? 【发布时间】:2019-11-01 02:59:49 【问题描述】:

在 Rails 6 中,我有一个带有文件字段的表单,并且我正在使用 activestorage 来存储文件。如果在提交表单后验证失败,则重新显示表单并显示验证错误。如何在重新显示表单时保留添加到文件字段的文件,以便用户不必再次将文件添加到表单?

rails 5 已经有一个类似的问题:Active Storage: Best practice to retain/cache uploaded file when form redisplays,但是那里的解决方案只适用于 Rails 5。

【问题讨论】:

您说“但是那里的解决方案仅适用于 Rails 5”。你有什么错误吗? 他链接到的帖子中的 cmets 解释说 - rails 6 不再在分配时存储文件,而是在保存时存储,这意味着那里使用的技术将无法访问所需的文件 糟糕,我的错。也许您应该考虑在记录验证之前使用模型保存附件,然后在保存时将它们附加到记录? 任何人都知道如何在不使用direct_upload的情况下做到这一点?我真的不喜欢我们必须做些什么来开放 CORS 以使其发挥作用。 【参考方案1】:

我找到了使用表单发布存储文件的解决方案(无需直接上传)。但它需要额外的代码到通常的脚手架代码@mention = Mention.create(mention_params)

控制器代码:

@mention.screenshot.blob.upload(mention_params[:screenshot])
@mention.screenshot.blob.save

在调试时检查它是否在 active_storage_blob 表中创建了一条记录。

上传文件后,您可以在下次提交时重复使用signed_id(当模型验证未通过时)。

查看代码:

f.hidden_field :screenshot, value: ...screenshot.signed_id if ...screenshot.attached? %>

这不是一个干净的解决方案,但我想你会明白的。

【讨论】:

【参考方案2】:

除了Robban回答,对于多个附件,做一些预览

  = f.file_field :attachments, multiple: true, direct_upload: true
  - f.object.attachments.each do |attach|
    = f.hidden_field :attachments, value: attach.signed_id, multiple: true
    = image_tag attach.preview(resize_to_limit: [100, 100]) if attach.previewable?
    = image_tag attach.variant(resize_to_limit: [100, 100]) if attach.variable?

【讨论】:

【参考方案3】:

由于 Rails 6 不存储分配文件,我找到的解决方法是在文件字段上启用直接上传。这将在表单提交之前通过 javascript 上传文件。

= f.file_field :doc, direct_upload: true

为此,您还需要将 activestorage.js 添加到您的包中,如Active Storage guide 中所述。

更改后,可以使用问题Active Storage: Best practice to retain/cache uploaded file when form redisplays 中描述的方法。这意味着将 signed_id 添加到表单中的隐藏字段中,如下所示:

= f.file_field :doc, direct_upload: true
= f.hidden_field :doc, value: f.object.doc.signed_id if f.object.doc.attached?

【讨论】:

不应该先隐藏字段吗? youtu.be/mG1BUMuSmsc?t=577 这在编辑已经有附件的项目时不起作用。它将保留现有的附件。

以上是关于在 Rails 6 中使用 activestorage 时,如何在重新显示表单时保留文件?的主要内容,如果未能解决你的问题,请参考以下文章

在 JS 模块中使用 Rails-UJS(带有 webpacker 的 Rails 6)

如何在 Rails 6.0.3.3 中使用 jQuery?

如何在 Rails 6 的视图中使用 JQueryUI

是否/为啥 Rails 6 仍在使用/推荐 CoffeeScript?

如何在 Rails 6 和 webpacker 中使用 morris.js?

在 Rails 6 中使用 activestorage 时,如何在重新显示表单时保留文件?