Rails中非持久记录的附件

时间:2019-04-22 08:26:27

标签: ruby-on-rails rails-activestorage

因此,我有一个items/new.html.erb页面,该页面具有用于新Items记录的表单。

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

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

我这样称呼图像:

Item

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

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

1 个答案:

答案 0 :(得分:1)

嵌套属性

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)并避免了孤立的记录,这是解决方案中一个非常实际的问题。 Referential integrity在优先级列表中应该很高。

这与视图中的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表中。但是据我所知,没有办法将附加元数据(例如订购)附加到附件。