The League of Extraordinary Developers

Telephone
0113 815 0986
Email
team@theled.co.uk

Blog

Whilst working on client projects we often find useful bits of information out. Where possible we blog about that information to pass on our knowledge. Below are some of our most recent entries.

Screengrab of the new LED site

PDF Generation in Rails

We were recently set the challenge by Bluestorm to create a PDF plugin for their in house Rails based CMS.

Having not done PDF generation in Rails before we needed a starting point and rather than doing some random searches on Google, we put out a few tweets to get advice from developers we knew and trusted. The most common piece of advice was to use Prawn with the Rails plugin Prawnto. We now had a starting point for PDF generation side of things.

The next stage was to start prototyping the document generation side of things. The client had provided wireframes of the functionality, and these included the ability to see the PDF being built on the fly as the editors added more and more content and imagery. The simplest solution here was show the PDF as a html document within the editing page.

We started the prototype by creating a series of user stories and putting those stories into Cucumber features. Within a short space of time we had our basic document creation functionality up and running. We were still left with one problem though. The generation of the PDF document.

Prawn and Prawnto

Having had these tools recommended to us we started testing how we could take our HTML preview and turn it into a PDF document. It didn't take us long to realise that using Prawn was going to become complicated and potentially pretty unflexible as the project developed.

Some sample code for Prawn PDF generation below:


# views/orders/show.pdf.prawn
pdf.text "Order ##{@order.id}", :size => 30, :style => :bold

pdf.move_down(30)

items = @order.cart.line_items.map do |item|
  [
    item.product.name,
    item.quantity,
    number_to_currency(item.unit_price),
    number_to_currency(item.full_price)
  ]
end

pdf.table items, :border_style => :grid,
  :row_colors => ["FFFFFF","DDDDDD"],
  :headers => ["Product", "Qty", "Unit Price", "Full Price"],
  :align => { 0 => :left, 1 => :right, 2 => :right, 3 => :right }

pdf.move_down(10)

pdf.text "Total Price: #{number_to_currency(@order.cart.total_price)}", :size => 16, 
            :style => :bold

As you can see, using Prawn would mean we would need to write a parser to convert our already existing HTML preview code into relevant Prawn related calls. Whilst this wouldn't be impossible, we like to keep our code as simple as possible, so future development is easier. We were also concerned how close the final PDF document would look to the HTML preview.

We decided we needed to look for some way to convert our HTML into a PDF document without the worry of the final document not looking exactly the same as the preview.

Prince XML and Princely

Prince XML is a command line tool that converts XML and HTML into PDF documents. To make things even easier their is a Rails wrapper for the library called Princely. So now we could use our existing view code to generate the PDF documents. We just needed to update our controller and bang, we were done.


def show
  respond_to do |format|
    format.html
    format.pdf do
      render :pdf => "filename", :stylesheets => ["application", "prince"], :layout => "pdf"
    end
  end
end

Easy right? Well, there was one thing that stopped us dancing around the office. Prince XML requires a Server Licence which costs $3,800. This was going to blow our client's budget.

Wicked PDF and wkhtmltopdf to the rescue!

Having just given up on the idea of Prince XML we found exactly what we were looking for in Wicked PDF, a rails plugin that uses wkhtmltopdf to generate PDF documents from HTML code.

The code to generate the PDF document was again very simple.


show.wants.pdf { 
  render :pdf => @print_publication.title,
          :template => 'admin/print_publications/show.pdf.erb',
          :layout => 'pdf.pdf.erb',
          :disable_javascript => false,
          :margin => {:top => 20,
                       :bottom  => 20,
                       :left  => 20, 
                       :right  => 20}, 
          :zoom => 2, 
          :disable_smart_shrinking => false, 
}

(Yes we are using resource_controller).

One thing to note is that we have enabled JavaScript as part of the PDF generation. We needed to use JavaScript in the view code as wkhtmltopdf doesn't support CSS 3 columns. It does have other CSS 3 support, just not columns. As the PDF documents required a two column structure we ended up using the Columnizer jQuery Plugin to generate the columns.

In our experience it was worthwhile disabling the smart shrinking in wkhtmltopdf as this caused some problems with the generated PDF not looking exactly the same as the HTML preview.

Conclusion

We can see that Prawn is a great library and is really powerful, but wkhtmltopdf offered us the ability to use the same view code for the HTML preview to generate the PDF document. This meant that anyone with HTML experience could generate a new PDF template easily.

Read more entries

Keep up to date

Blog RSS feed

Want to find out more?

If we have piqued your interest then we'd love to hear from you.

Get in contact with us

Services

  • Ruby on Rails
  • .Net
  • PHP
  • HTML5
  • CSS3
  • JavaScript
  • Web Apps
  • Mobile Web Apps
  • iOS Apps

Blog

  1. Blog title
    C4DI and the magical coffee beans
    Post Date
    Thursday, September 05 2013
  1. Blog title
    Designers - how far should their coding knowledge go?
    Post Date
    Thursday, May 30 2013
  1. Blog title
    Twitter Bootstrap - It's not all roses
    Post Date
    Friday, June 22 2012
  1. Blog title
    Keep your requests thin
    Post Date
    Friday, January 06 2012
  1. Blog title
    Storing a Product Catalog for eCommerce with a Document Database
    Post Date
    Monday, November 21 2011
  1. Blog title
    Success for Incentive Maker - Hull Digital Post
    Post Date
    Friday, July 08 2011
RSS

Twitter

Follow