web-dev-qa-db-fra.com

Rails 5.2 Active Storage ajouter des attributs personnalisés

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).

15
paxer

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é.

16
George Claghorn