J'ai un modèle avec des pièces jointes:
class Project < ApplicationRecord
has_many_attached :images
end
Lorsque j'attache et enregistre l'image, je souhaite également enregistrer un attribut personnalisé supplémentaire - display_order
(Entier) avec l'image jointe. Je veux l'utiliser pour trier les images jointes et les afficher dans l'ordre que j'ai spécifié dans cet attribut personnalisé. J'ai examiné le code source d'ActiveStorage pour la méthode #attach
Ainsi que pour le modèle ActiveStorage::Blob
Mais il semble qu'il n'y ait pas de méthode intégrée pour transmettre des métadonnées personnalisées.
Je me demande, quelle est la façon idiomatique de résoudre ce problème avec ActiveStorage? Dans le passé, j'ajoutais généralement un attribut display_order
Au modèle ActiveRecord qui représente ma pièce jointe, puis je l'utilisais simplement avec la requête .order(display_order: :asc)
.
Si vous devez stocker des données supplémentaires avec chaque image et effectuer des requêtes basées sur ces données, je vous recommande d'extraire un modèle Image
qui enveloppe un file
attaché:
# 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 %>
Notez que l'exemple de vue ci-dessus provoque 2N + 1 requêtes pour un projet avec N images (une requête pour les images du projet, une autre pour chaque image ActiveStorage::Attachment
enregistrement, et un de plus pour chaque pièce jointe ActiveStorage::Blob
). J'ai délibérément évité d'optimiser le nombre de requêtes par souci de clarté.