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 = Prawn::Document.new eval(Invoice.get_pdf_markup(invoices)) pdf.render_file(filename) end
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"
else
point = [pdf.bounds.right-50, pdf.bounds.bottom + 648]
page_counter = pdf.lazy_bounding_box(point, :width => 10) do
pdf.text pdf.page_count, :size => 9, :align => :right
end
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
end
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 Date.today.strftime("%m/%d/%Y"), :align => :right, :size => 9
end
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
end
end
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
end
end
page_counter.draw
end
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
end
end
EOS
end
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(File.read(filename), :type => "application/pdf",
:filename => "#{Date::MONTHNAMES[params[:month]]}#{params[:year]}.pdf")
Filed under: Ruby on Rails | Leave a Comment
Tags: pdf, prawn, rails, ruby, Ruby on Rails
Search
-
Blogroll