I have has_many_attached images relationship in Post model. 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?
When you add the has_many_attached macro to a class it actually adds the following relationships to your 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
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. 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.
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
<% @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.