October 13, 2008
Older: Some Design Attention
Newer: Suggest a Topic Today
How To Generate PDFs in Rails With Prawn
It’s been a while since I’ve needed to generate a PDF in ruby. I typically discourage clients from it because, well, I’m lazy and it’s a pain. I’ve always kind of hated pdf generation. It has always felt a tad awkward, be it in PHP, ColdFusion (6, unfortunately before cfdocument) and even Ruby. This time around, I decided to try out the new kid on the block, Prawn. On the website I just linked to, they recommend the prawnto plugin, so I gave it a whirl. My conclusions are that they work pretty well. Granted, I was just creating some text and formatting it, but I got up and running quickly. For your enjoyment, I’ll cover some basics below.
Create and Install
Note: I’m assuming Rails 2.1+. Fire up terminal and create a new app and install the prawnto plugin.
rails prawn_demo
sudo gem install prawn
script/plugin install git://github.com/thorny-sun/prawnto.git
Now add prawn as a dependency in environment.rb.
config.gem 'prawn'
For the sake of the demo we’ll need some demo data. Let’s create a Book model with some columns that we can shove lorem ipsum into.
script/generate scaffold book title:string author:string description:text
rake db:migrate
BooksController#show Example
I ran over to The Pragmatic Programmer’s site and snagged a few titles to enter as test data. Let’s get started with something simple and add a pdf version of the show action. Open up the books controller and add format.pdf { render :layout => false }
so that the action looks something like this:
def show
@book = Book.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => @book }
format.pdf { render :layout => false }
end
end
Now if you visit http://localhost:3000/books/2.pdf, you’ll get a template is missing error. Let’s add the show view. The prawnto plugin adds all the wiring, so all you need to do is create the show.pdf.prawn file inside app/views/books. For now, lets hello world that mofo with the following:
pdf.text "Hello World!"
Now if you revisit that url, you’ll get a pdf that says hello world. Simple, eh? Let’s make the view specific to the book and tweak the look a bit.
pdf.font "Helvetica"
pdf.font.size = 13
pdf.text "Book: #{@book.title}", :size => 16, :style => :bold, :spacing => 4
pdf.text "Author: #{@book.author}", :spacing => 16
pdf.text @book.description
The first two lines set the default font stuff. As you can see, pdf.text
takes a string and then a hash of options. :size
adjust the font size, :style
changes the weight, and :spacing
controls the space between lines. Pretty self-explanatory, but I thought I would cover it anyway.
BooksController#index Example
Now let’s create a pdf of all the books with each book on it’s own page. Add format.pdf { render :layout => false }
to the respond to block in the index action and create the following index.pdf.prawn view:
pdf.font "Helvetica"
pdf.font.size = 13
@books.each do |book|
pdf.text "Book: #{book.title}", :size => 16, :style => :bold, :spacing => 4
pdf.text "Author: #{book.author}", :spacing => 16
pdf.text book.description
pdf.start_new_page
end
So the examples I showed were pretty basic and there is a lot more you can do with prawn, but I didn’t feel like coming up with examples. Helpers work just like in views which is handy. Also, prawn does images and data tables in a pretty simple manner. Check out the prawn and prawnto websites for more.
5 Comments
Oct 14, 2008
It’s awesome that Prawn supports utf8 by default – that’s what was missing in almost all pdf generators in Ruby
Oct 14, 2008
For anyone using JRuby Flying Saucer (https://xhtmlrenderer.dev.java.net/) might be from interest. It generates PDFs from an XHTML input which I guess we all know how to build and design with.
I worked with it once but in “normal” Java not JRuby and it was a great pleasure to do so. Never seen so harmless PDF generation again.
Oct 14, 2008
Did you compare it with fpdf? Do you think, it is better?
Oct 14, 2008
@Vidmantas – That is cool.
@Infakta – I’ve used fpdf back in my php days but never with ruby. The only ruby version of fpdf I could find doesn’t feel rubyish at all.
Oct 19, 2008
I use rfpdf (fpdf in ruby) and it is fine. Is is problem with uft-8 encoding, but we can solve it.
Sorry, comments are closed for this article to ease the burden of pruning spam.