简体   繁体   English

在 Active storage Rails 5.2 中按文件名排序多个图像

[英]Order multiple images by filename in Active storage Rails 5.2

I have has_many_attached images relationship in Post model.我在 Post 模型中有 has_many_attached 图像关系。 I want to order the images by their filename when showing them on the Post show page.我想在发布展示页面上显示图像时按文件名对图像进行排序。 How can I order by filename?如何按文件名排序?

Example:例子:

<% @post.images.order("id DESC").each do |image| %>

Is it possible to just order by filename through something like active_storage_blob.filename or something?是否可以通过诸如 active_storage_blob.filename 之类的文件名进行排序?

When you add the has_many_attached macro to a class it actually adds the following relationships to your class当您将 has_many_attached 宏添加到类时,它实际上将以下关系添加到您的类中

  class Post < ApplicationRecord
     has_many :image_attachments, -> { where(name: 'image') }, class_name: "ActiveStorage::Attachment", as: :record, inverse_of: :record, dependent: false
     has_many :image_blobs, through: :image_attachments, class_name: "ActiveStorage::Blob", source: :blob
  end

This means we can leverage the relationship to handle sorting by filename which is actually an attribute of the ActiveStorage::Blob rather than the attachment.这意味着我们可以利用这种关系来处理按filename排序, filename实际上是ActiveStorage::Blob一个属性,而不是附件。 To do this we reference to the relation defined in by the macro images in your case and then join to its natural relationship to the ActiveStorage::Blob so that we can sort based on these fields.为此,我们参考您的案例中由宏images定义的关系,然后join其与ActiveStorage::Blob自然关系,以便我们可以根据这些字段进行排序。

The final result would be最终结果将是

   <% @post.images.joins(:blobs).order('active_storage_blobs.filename ASC').each do |image| %>

Now all of the images will be sorted by the filename however since joins does not actually load any data and I am assuming you are referencing the the file name in your view we could also use现在所有的图像都将按文件名排序,但是由于 joins 实际上并没有加载任何数据,我假设您在视图中引用了文件名,我们也可以使用

   <% @post.images.includes(:blobs).references(:blobs).order('active_storage_blobs.filename ASC').each do |image| %>

To have a single query that loads the images and the ActiveStorage::Blob data all at once to avoid the n + 1 issues that could arise from the original version.使用单个查询同时加载图像和ActiveStorage::Blob数据,以避免原始版本可能出现的 n + 1 问题。

For Rails 6 I needed对于 Rails 6 我需要

@post.images.includes(:blob).references(:blob).order('active_storage_blobs.filename ASC').each do |image|
  # ...
end

If you have the class setup with ActiveStorage like:如果您使用 ActiveStorage 进行类设置,例如:

class Post < ApplicationRecord
  has_many_attached :images
end

You can run this to order and avoid N+1 queries您可以运行它来订购并避免 N+1 查询

@post.images.includes(:blob).references(:blob).order(:filename)

If anyone is googling for general<\/strong> solution how to reorder has_many_attached<\/code> attachments you can do it by adding a Array\/JSON-Array\/Serialized field to the model which declares the has_many_attached<\/code> and store ids of ActiveStorage::Attachment in order.如果有人在谷歌上搜索如何重新排序has_many_attached<\/code>附件的通用<\/strong>解决方案,您可以通过向模型添加一个 Array\/JSON-Array\/Serialized 字段来声明has_many_attached<\/code>并按顺序存储 ActiveStorage::Attachment 的 id。 Then you can do something like:然后您可以执行以下操作:

# app/models/entry.rb
class Entry < ApplicationRecord
  has_many_attached :pictures


  def ordered_pictures
    pictures.sort_by{ |pic| ordered_picture_ids.index(pic.id) || (pic.id*100) }
  end

  def ordered_picture_ids=(ids)
    super(ids.map(&:to_i)) # convert any ids passed to this method to integer
                           # this is just for security reasons,
                           # you don't need to do this for the feature to work
  end
end

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM