Create a PDF Invoice in Rails

Create a PDF Invoice Using Prawn in Rails

After coming to the realization that I was going to need to create PDFs on the fly for the rails application I’m working on for a client, I started my hunt for something that could get the job done quick with minimal effort. The Prawn gem was highly recommended by other rails enthusiasts.

This tutorial is old and may not work with newer versions of Rails 3+ and Prawn without some modifications. I’ve only tested this in a Rails 2.3.x environment, but I do plan to do an updated article in the future when I have time.

Perhaps the greatest gripe I had about Prawn on first encounter was the lack of being able to use CSS and HTML for easy styling, which is something I’m much more comfortable with from experience. But after realizing that there weren’t many candidates that allowed this type of styling format in PDFs, I decided to give Prawn a go anyhow.

I also found prawnto googling, which is a plugin used with Prawn to provide easy access to the prawn library and allows for a simple respond_to block slapped into your controller to provide you with the .pdf extension. This seemed perfect for what I needed so I figured I’d share my knowledge with others.

Lets Get Started

Let’s do some scaffolding to save some time. In this case we are going to create invoices for our customers.

Launch your server like so:

Time to create a new customer invoice that we can work with. Go to your http://localhost:3000/invoices page and click on new invoice and add some data; here is what I used:

Name: Branden Silva
Item Name: Awesome Serif Fonts
Item Price: 24.99
Item Quantity: 2

Once done, http://localhost:3000/invoice/1 should now be your first customer invoice. Awesome, now lets get prawn and prawnto installed.

Getting Prawn and Prawnto Up and Running

I’m using rails 2.3.5 for reference so your results may vary depending on what version you are running. First you’ll want to download the prawn gem and prawnto plugin into your project like so:

Note: If you end up getting a “uninitialized constant Mime::PDF” error further down the tutorial when launching the pdf then prawnto may have not installed correctly. I recommend you go download prawnto at the git repository here and create a folder prawnto under your vendor/plugins directory in your rails application and stash the files in there.

Then your going to want to add prawn to your environment.rb file to avoid any dependency issues in the future:

Then you are going to have to set up prawnto in your invoice controller. Here I’m going to fetch a customer invoice and display a pdf in my show action when a user adds a .pdf extension to the url. The part you’ll want to pay attention to and add is the format.pdf line.

Now your going to need to create a file to put your prawn code into. In this case I just create a blank show.pdf.prawn file under the http://localhost:3000/views/invoices folder.

Now Its Time to Start Dishing Some Prawn

Lets start writing some prawn code. You can access your PDF at any time by simply adding a .pdf extension to your individual customer invoices. So http://localhost:3000/invoices/1 is how you show your customer invoice information via the browser and http://localhost:3000/invoices/1.pdf would be how you access your customer invoice via PDF format. Of course it’s not going to do anything until we write some code so open up your show.pdf.prawn file.

I usually start off by adding an image to my pdfs to give them a nice spiffy look. Here is the awesome logo I’m going to use:

Now save your logo (or mine) to your public/images directory in your rails app. This way you can reference it in your show.pdf.prawn file. Here is what the code looks like in our show.pdf.prawn file to add this image:

We are simply creating a local variable called logopath and then displaying it with the pdf.image method off our pdf object. I’ve also set the width and height of the image here.

How about we add some text now to our PDF. First lets shift the page down 70 points, add some styling, and then we can access our lovely instance variables that come with our rails app to pull in dynamic data.

Thats a big chuck of code so let me break it down for you. pdf.move_down shifts your cursor focus down the PDF document. This doesn’t apply to our pdf.text_box which is entirely different creature that doesn’t follow the normal pdf page flow (you can think of text_boxes like absolute divs in html). pdf.font allows you to use supported prawn fonts. I’m sure it can be extended but I haven’t researched it in depth because Helvetica fits my needs for this example and client project. pdf.font_size adjusts the size of your text.

So what would we you do if you needed a table? Simple enough, try this:

Here we are creating a multi-dimensional array and assigning it values from our rails application. In this case our local variable invoiceinfo is storing our table information. You don’t have to put the information in it’s own variable but I find its easier to keep the data separate from the formatting of the table. #{@invoice.item_name} would pull our item name from our rails application and display it in our pdf, yeah, it’s that easy. pdf.table calls invoiceinfo and then assigns a few attributes to that table. Pretty awesome that it’s that clean and simple to style everything up with a few key value pairs. I’ve even added some row colors to make it easier to scan for the user.

However, a PDF wouldn’t be complete without allowing page numbers. Fairly straightforward to do in prawn as well, here is the code:

Here we shrink the pdf.font_size down so the page number won’t be enormous. We start to get into the pdf.bounding_box. You can basically define boxes inside your pdf. In this case we are telling the bounding_box to find the right most edge (bounds) of the box you are in, which happens to be the pdf document, then we subtract 50 points. We do the same thing with the bottom minus the shift of 50 points. We then slap a width and height to our bounding box and perform a block of code in the bounding_box. the local variable count is assigned and then displayed with pdf.text.

Heres my final example for Download.

Well there you have it; a simple invoice with very little effort. With some additional research you can add more data and style it further to fit your needs. Before you go though lets add a nice link to our PDF on our main show page so the customer can find it without having to type it in the URL manually. Head over to your views folder and open your http://localhost:3000/invoices/show.html.erb file. Then you’ll want to add this code somewhere in your file:

We’re basically just calling the invoices path and throwing it the invoice with an extension of pdf attached to the end of it. This should show up as a link now so when your customer clicks on it they will be redirected to the PDF version of your data in your rails application.

Conclusion

Prawn is definitely a simple and easy way to get PDFs up and going with very minimal effort. The only downsides I’ve noticed from my perspective is it’s not completely possible to style ever nook and cranny because your at the whims of Prawns formatting options; but I’m guessing it won’t make much of a difference because there aren’t to many alternatives as nice as Prawn or that have this simple functionality. Documentation was available, but examples were limited but nothing a Google search can’t net you. Hopefully this helps out some of those in pursuit of a quick PDF solution.

Final Note: Prawnto’s website mentions it only been updated to rails 2.2 but I had no problems getting it to work on 2.3.5. It may however be broken in rails 3 so just be aware of that when upgrading.

Other Resources