Save a Prawn PDF as a Paperclip attachment?
Asked Answered
S

5

23

I'm using Prawn and Prawnto to display a PDF-based reports to the user, but in some circumstances, I'd also like to save the PDF as an attachment to one of my models. I'm using Paperclip for all of my attachments. Does anyone have any suggestions on how to do this?

Thanks!

Sentry answered 17/2, 2011 at 21:25 Comment(0)
K
27

When using prawnto you will need to eval the variables in the .pdf.prawn template. Second step is to mimic a real file for paperclip.

  1. Generating the PDF:

    #find the prawwnto template you want
    template = File.read("#{RAILS_ROOT}/app/views/reports/your_report.pdf.prawn")
    
    pdf = Prawn::Document.new(:page_size => 'A4', :your_options => :etc)
    
    pdf.instance_eval do
      @report = find_report #put here, all local variables that the pdf template needs
      eval(template) #this evaluates the template with your variables
    end
    
    attachment = pdf.render
    
  2. Save PDF with paperclip:

    file = StringIO.new(attachment) #mimic a real upload file
    file.class.class_eval { attr_accessor :original_filename, :content_type } #add attr's that paperclip needs
    file.original_filename = "your_report.pdf"
    file.content_type = "application/pdf"
    
    
    #now just use the file object to save to the Paperclip association.
    
    
    # assuming your Paperclip association is named "pdf_report"
    @report_store.pdf_report = file
    @report_store.save!
    

Hope this helps.

Kindred answered 24/2, 2011 at 23:52 Comment(1)
I found this hugely helpful for generating pdfs from a model method. One slip-up I ran into is that you have to name the output of Prawn::Document.new "pdf" if your prawnto templates use the pdf.method_name style. Thanks!Izaak
R
10

It should work if you just pass a File reference to that PDF to Paperclip.

require 'prawn'
pdf = Prawn::Document.new
pdf.text("Prawn Rocks")
pdf.render_file('/path/to/prawn.pdf')

pdf_file = File.open('/path/to/prawn.pdf')

# assuming your Paperclip association is named "pdf_attachment"
my_model.pdf_attachment = pdf_file
Riboflavin answered 18/2, 2011 at 4:27 Comment(0)
R
2

I got it working without instance eval by turning it the other way around : generate the PDF in your model and render it in you controller

In a model :

  def generate_pdf
    Prawn::Document.new(:page_size => 'A4', :top_margin => 0, :left_margin => 0) do |pdf|
        <your pdf code here>
        <copy paste from your template>
    end.render
  end

You can then send it as a mail attachment :

attachment = generate_pdf
mail = Notifier.send_pdf(attachment)
mail.deliver

Or render it in your browser windows in your controller :

send_data your_model.generate_pdf, :type => "application/pdf", :disposition => 'inline'
Redroot answered 2/12, 2013 at 17:33 Comment(1)
^This was a perfect answer on how to use a common Prawn generation routine and render either screen or email. Thanks!Alterable
Q
1

This worked for me

pdf = Prawn::Document.new(:page_size => "LETTER", :page_layout => :landscape)
pdf.render_file File.join(Rails.root, "app/pdfs", "x.pdf")
current_user.certificate = File.open("#{Rails.root}/app/pdfs/x.pdf")
current_user.save!

Where certificate is what my paperclip attachment is saved as in the model:

class User < ActiveRecord::Base
  has_attached_file :certificate
Quintin answered 28/9, 2014 at 0:34 Comment(0)
G
0

@Adam Albrecht,You will be saving image as a attachment but for saving pdf as an attachment you need to add one more validation -

****validates_attachment :document, content_type: { content_type: 'application/pdf' }****

Gothicize answered 29/1, 2015 at 12:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.