web-dev-qa-db-fra.com

Utilisez Rails 5.2 ActiveStorage pour créer et enregistrer un pdf et le joindre ultérieurement à un e-mail

J'ai bien peur de me tromper complètement avec la nouvelle fonctionnalité de stockage actif. Ce que je veux faire, c'est créer un pdf (j'utilise WickedPdf) et le joindre à un modèle. Voici le premier problème, La seule chance que j'ai trouvée jusqu'à présent est d'écrire d'abord dans un fichier, puis d'ouvrir ce fichier pour créer la pièce jointe.

self.document.attach( {
  filename: "filename.pdf",
  io: File.open(pdf_document)
})

Existe-t-il un moyen de créer la pièce jointe à partir d'une chaîne?

Ensuite, j'essaie de joindre ce fichier à un courrier. Cela échoue car il a besoin à nouveau d'un fichier, pas d'un blob.

attachments[document.filename.to_s] = document.blob

La recréation d'un fichier me semble vraiment bizarre.

Quelqu'un peut-il m'éclairer sur la bonne façon d'y parvenir sans écrire de fichiers? Je semble inutile, inefficace et prend du temps pour moi.

=====

Solution Partie 2: J'ai donc réussi à joindre le document sans créer de fichier

attachments[document.filename.to_s] = {:mime_type => 'application/pdf',
                               :content => document.attachment.blob.download }

La première partie est toujours manquante. J'espère que quelqu'un a une réponse!

19
Markus Andreas

Je crois que si vous générez quelque chose comme un PDF, vous voudrez utiliser l'option io lorsque vous joignez. C'est ainsi que je fais les choses dans une application maintenant.

Par exemple, voici ce que la documentation montre :

person.avatar.attach(params[:avatar]) # ActionDispatch::Http::UploadedFile object
person.avatar.attach(params[:signed_blob_id]) # Signed reference to blob from direct upload
person.avatar.attach(io: File.open("/path/to/face.jpg"), filename: "face.jpg", content_type: "image/jpg")
person.avatar.attach(avatar_blob) # ActiveStorage::Blob object

Comme il apparaît dans la documentation, sauf si vous avez un ActionDispatch::Http::UploadedFile, vous voudrez utiliser l'option io.

Quant à joindre le fichier à un e-mail, vous pouvez avoir quelques options. Si vous avez toujours accès à pdf_document, vous pouvez le faire. Je ne sais pas exactement de quel type d'objet il s'agit.

attachments[document.filename.to_s] = pdf_document.read

Mise à jour

J'ai déjà utilisé wicked_pdf, mais pas depuis un moment. Il semble que la plupart des méthodes de génération renvoient une chaîne sauf si vous demandez un fichier à la place. Vous le savez peut-être déjà - donnant juste quelques informations pour la réponse.

Puisque wicked_pdf peut renvoyer une chaîne, je pense que vous pouvez utiliser StringIO pour joindre le fichier. Par exemple:

pdf = WickedPdf.new.pdf_from_string("<h1>Hey</h1>")
self.document.attach(io: StringIO.new(pdf), filename: "file.pdf", content_type: "application/pdf")

StringIO fait exactement comme son nom l'indique. Il prend une chaîne et la fait se comporter comme un IO. Une fois que vous avez un IO, vous pouvez l'utiliser avec ActiveStorage comme si vous aviez un fichier ouvert.

Ensuite, comme vous l'avez mentionné dans votre question mise à jour, vous pouvez télécharger le fichier et le joindre à l'e-mail.

21
Derek Hopper