Saving a Prawn PDF to File


On a recent project I was generating a PDF using Prawn and feeding it out to the user via send_data.  Then requirements changed (of course), and we needed to show past invoices.  To improve response times I was asked to save the generated PDFs as they wouldn’t change and the storage of them is not an issue.

Unfortunately Prawn doesn’t seem to support this functionality on it’s own, and there weren’t too many guides for how to do this out there.

Fortunately, it turned out to be pretty easy to implement.  I set up a static method in my Invoices class that takes in teh desired file name, and the list of invoices:

def self.create_pdf(invoices, filename)
   pdf =


And another static method to get the PDF markup.  Mine’s pretty long and complicated since it’s a formatted invoice.  Just put what would normally be in your prawn.pdf file here.

 def self.get_pdf_markup(invoices)
 return <<-EOS
 if invoices.blank?
 pdf.text "There has been no account activity this month"
 point = &#91;pdf.bounds.right-50, pdf.bounds.bottom + 648&#93;
 page_counter = pdf.lazy_bounding_box(point, :width => 10) do
 pdf.text pdf.page_count, :size => 9, :align => :right

 pdf.header [pdf.margin_box.top_left] do
 pdf.fill_color "299f6f"
 pdf.text "STATEMENT", :align => :center, :size => 9

 pdf.bounding_box [300,670], :width=>100 do
 pdf.text "Customer No:", :size => 9
 pdf.text "Date: ", :size => 9
 pdf.text "Page: ", :size => 9

 pdf.bounding_box [400, 670], :width=> 100 do
 pdf.fill_color "000000"
 pdf.text invoices.first.invoice.accpac_customer.IDCUST.strip, :align => :right, :size => 9
 pdf.text"%m/%d/%Y"), :align => :right, :size => 9

 logo_header = "#{RAILS_ROOT}/public/images/logo.png"
 pdf.image logo_header, :width => 225, :at => [5, 680]

 pdf.bounding_box [50,600], :width => 200 do
 pdf.fill_color "299f6f"
 pdf.text "Sold To:", :size => 9
 pdf.bounding_box [10, 0], :width => 190 do
 pdf.fill_color "000000"
 pdf.text invoices.first.invoice.accpac_customer.display_address.split("
")* "\n", :size => 9
 pdf.text invoices.first.invoice.accpac_customer.TEXTPHON1, :size => 9

 pdf.bounding_box [300,600], :width => 200 do
 pdf.fill_color "299f6f"
 pdf.text "Remit To Address:", :size => 9

 pdf.bounding_box [10, 0], :width => 190 do
 pdf.fill_color "000000"
 pdf.text REMIT_TO_ADDRESS * "\n", :size => 9

 data = invoices.collect{|arobl| [arobl.IDINVC, Date.strptime(arobl.DATEINVC.to_s, '%Y%m%d').strftime('%Y/%m/%d'),
 arobl.TRXTYPETXT, "", Date.strptime(arobl.DATEDUE.to_s, '%Y%m%d').strftime('%Y/%m/%d'), sprintf("%0.2f", arobl.AMTDUETC) ]}
 pdf.fill_color "000000"
 pdf.bounding_box [0,500], :width => 500 do
 pdf.table data,
 :position => :center,
 :header_text_color => "299f6f",
 :border_color => "299f6f",
 :headers => ["Document No.", "Doc. Date", "Ty.", "Reference/Applied No.", "Due Date", "Amount" ],
 :font_size => 9,
 :width => 500,
 :vertical_padding => 1


And to return that from your controller all you have to do is a send_data (or send_file, I opted for send_data) call with the file:

 send_data(, :type => "application/pdf",
 :filename => "#{Date::MONTHNAMES[params[:month]]}#{params[:year]}.pdf")

No Responses Yet to “Saving a Prawn PDF to File”

  1. Leave a Comment

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: