October 13, 2008

Posted by John

Tagged gems, pdf, plugins, and prawn

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

  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.

About

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

Projects

Flipper
Release your software more often with fewer problems.
Flip your features.