首页 > 解决方案 > Rails 中非持久记录的附件

问题描述

所以我有一个items/new.html.erb页面,其中有一个新Items记录的表单。

现在该页面还有一个图像上传部分,在新记录表单旁边,用户可以上传多个图像。此 UI 设计建议用户应该能够上传图像,或将图像附加到要创建的记录。

我当前的设置是当用户在页面中上传图像(这是通过 AJAX/rails UJS 处理的)时,id上传的图像/图像将被添加到新Item表单的隐藏字段中。然后只有在提交主表单时,图像才会附加到新创建的Item资源中。我觉得这是处理这个问题的一种不同寻常的方式,并且有一种更简单、更清晰的 Rails 方式来解决这个问题。

我这样称呼图像:

item.images

该页面还允许用户对图像附件的顺序进行排序或更新,但我认为这是一个应该在另一个讨论中的主题。

您如何在 Rails 中正确而清晰地处理这个问题,第一个问题?

标签: ruby-on-railsrails-activestorage

解决方案


嵌套属性

Rails 有一个内置机制,称为accepts_nested_attributes. 这使您可以在同一请求中创建嵌套记录:

class Item
  has_many :images
  accepts_nested_attributes_for :images
end

class Image
  belongs_to :item
  has_one_attached :file
end

这将让您创建一个项目和图像:

Item.create(name: 'Foo', image_attributes: [{ file: 'foo.jpg'}, { file: 'bar.jpg'}])

ActiveRecord 将处理以正确顺序插入记录。

这允许您拥有一个不可为空的外键 ( item_id) 并避免孤立记录,这对您的解决方案来说是一个非常现实的问题。参照完整性在您的优先级列表中应该非常重要。

这在模型fields_for中与视图(表单)一起使用。

<%= form_with(model: @item) do |form| %>
  <%= form.fields_for(:images) do |image_fields| %>
    <%= image_fields.file_field :file %>
  <% end %>
<% end %>

通过在强参数中传递一个键数组:

params.require(:item).permit(:name, image_attributes: [:file])

ActiveStorage 的has_many_attached

ActiveStorage 还允许您使用has_many_attached. 附件存储在active_storage_attachments表中。但是,据我所知,无法将其他元数据(例如排序)附加到附件。


推荐阅读