October 13th, 2008

Posted by John

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.

Tags: , , ,

5 Responses to “How To Generate PDFs in Rails With Prawn”

  1. It’s awesome that Prawn supports utf8 by default – that’s what was missing in almost all pdf generators in Ruby

  2. 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.

  3. Did you compare it with fpdf? Do you think, it is better?

  4. @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.

  5. 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. If you have any further comments, just send me an email.

About

Authored by John Nunemaker (Noo-neh-maker), a web developer and programmer who has fallen deeply in love with Ruby. More about John.

Syndication

Feed IconRailsTips Articles - An assortment of howto's and thoughts on Ruby and Rails.

Feed IconRails Quick Tips - Ruby and Rails related links that I find. Never more than 5 a day.