30

我有一个带附件的模型:

class Project < ApplicationRecord
  has_many_attached :images
end

当我附加并保存图像时,我还想保存一个附加的自定义属性 - display_order(整数)和附加的图像。我想用它对附加的图像进行排序,并按照我在这个自定义属性中指定的顺序显示它们。我已经查看了#attach方法和ActiveStorage::Blob模型的 ActiveStorage 源代码,但看起来没有内置方法可以传递一些自定义元数据。

我想知道,用 ActiveStorage 解决这个问题的惯用方法是什么?过去,我通常只display_order在 ActiveRecord 模型中添加一个代表我的附件的属性,然后简单地将其与.order(display_order: :asc)查询一起使用。

4

2 回答 2

40

如果您需要为每个图像存储其他数据并根据该数据执行查询,我建议您提取一个Image包装附加的模型file

# app/models/project.rb
class Project < ApplicationRecord
  has_many :images, dependent: :destroy
end
# app/models/image.rb
class Image < ApplicationRecord
  belongs_to :project

  has_one_attached :file
  delegate_missing_to :file

  scope :positioned, -> { order(position: :asc) }
end
<%# app/views/projects/show.html.erb %>
<% @project.images.positioned.each do |image| %>
  <%= image_tag image %>
<% end %>

请注意,上面的示例视图会导致对具有 N 个图像的项目进行 2N+1 次查询(一次查询项目的图像,另一个查询每个图像的ActiveStorage::Attachment记录,以及每个附加的查询ActiveStorage::Blob)。为了清楚起见,我故意避免优化查询数量。

于 2018-03-27T19:27:58.960 回答
0

如果您只需要订购图像,您可以自定义文件名并按文件名订购图像。我使用我强烈推荐的羽绒宝石。

例如:

image = Down.download(image_url)
filename = "description-#{order}"
@object.images.attach(io: image, filename: filename)

然后在 @object 的控制器中:

@images = @object.images_attachments.joins(:blob).order('active_storage_blobs.filename ASC')

然后在你看来@object

<%@images.each do |image|%>
<%= image_tag image%>
<% end %>
于 2021-02-11T06:34:31.557 回答