按活动存储中的文件名排序多个图像 Rails 5.2
Order multiple images by filename in Active storage Rails 5.2
我在 Post 模型中有 has_many_attached 个图像关系。在 Post 显示页面上显示图像时,我想按文件名对图像进行排序。如何按文件名排序?
示例:
<% @post.images.order("id DESC").each do |image| %>
是否可以通过 active_storage_blob.filename 之类的方式按文件名排序?
当您将 has_many_attached 宏添加到 class 时,它实际上将以下关系添加到您的 class
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
这意味着我们可以利用关系来处理 filename
的排序,这实际上是 ActiveStorage::Blob
的属性而不是附件。为此,我们参考您的案例中宏 images
定义的关系,然后 join
参考其与 ActiveStorage::Blob
的自然关系,以便我们可以根据这些字段进行排序。
最终结果会是
<% @post.images.joins(:blobs).order('active_storage_blobs.filename ASC').each do |image| %>
现在所有图像都将按文件名排序,但是由于连接实际上不会加载任何数据,我假设您在视图中引用文件名,我们也可以使用
<% @post.images.includes(:blobs).references(:blobs).order('active_storage_blobs.filename ASC').each do |image| %>
使用一个查询同时加载图像和 ActiveStorage::Blob
数据,以避免原始版本可能出现的 n + 1 个问题。
如果您有 class ActiveStorage 设置,例如:
class Post < ApplicationRecord
has_many_attached :images
end
您可以运行这个来订购并避免 N+1 查询
@post.images.includes(:blob).references(:blob).order(:filename)
对于Rails 6 我需要
@post.images.includes(:blob).references(:blob).order('active_storage_blobs.filename ASC').each do |image|
# ...
end
如果有人在谷歌上搜索 general 解决方案如何重新排序 has_many_attached
附件,您可以通过向模型中添加一个 Array/JSON-Array/Serialized 字段来声明has_many_attached
并按顺序存储 ActiveStorage::Attachment 的 ID。然后你可以这样做:
# 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
如果你不明白我的意思,我写了更详细的文章:https://blog.eq8.eu/article/order-attachments-in-rails-activestorage-has_many_attached.html
我在 Post 模型中有 has_many_attached 个图像关系。在 Post 显示页面上显示图像时,我想按文件名对图像进行排序。如何按文件名排序?
示例:
<% @post.images.order("id DESC").each do |image| %>
是否可以通过 active_storage_blob.filename 之类的方式按文件名排序?
当您将 has_many_attached 宏添加到 class 时,它实际上将以下关系添加到您的 class
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
这意味着我们可以利用关系来处理 filename
的排序,这实际上是 ActiveStorage::Blob
的属性而不是附件。为此,我们参考您的案例中宏 images
定义的关系,然后 join
参考其与 ActiveStorage::Blob
的自然关系,以便我们可以根据这些字段进行排序。
最终结果会是
<% @post.images.joins(:blobs).order('active_storage_blobs.filename ASC').each do |image| %>
现在所有图像都将按文件名排序,但是由于连接实际上不会加载任何数据,我假设您在视图中引用文件名,我们也可以使用
<% @post.images.includes(:blobs).references(:blobs).order('active_storage_blobs.filename ASC').each do |image| %>
使用一个查询同时加载图像和 ActiveStorage::Blob
数据,以避免原始版本可能出现的 n + 1 个问题。
如果您有 class ActiveStorage 设置,例如:
class Post < ApplicationRecord
has_many_attached :images
end
您可以运行这个来订购并避免 N+1 查询
@post.images.includes(:blob).references(:blob).order(:filename)
对于Rails 6 我需要
@post.images.includes(:blob).references(:blob).order('active_storage_blobs.filename ASC').each do |image|
# ...
end
如果有人在谷歌上搜索 general 解决方案如何重新排序 has_many_attached
附件,您可以通过向模型中添加一个 Array/JSON-Array/Serialized 字段来声明has_many_attached
并按顺序存储 ActiveStorage::Attachment 的 ID。然后你可以这样做:
# 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
如果你不明白我的意思,我写了更详细的文章:https://blog.eq8.eu/article/order-attachments-in-rails-activestorage-has_many_attached.html