Generating PDFs In Rails Application Using DocRaptor
This post is sponsored by DocRaptor.com
One of the most common & requested feature I come across when building applications is supporting export data in popular formats like pdf and excel. In the past, I have used multiple libraries to generate these format but the no. of dependencies required to make it all work goes it usually goes out of hand pretty quickly. I have spent countless no. of hours getting the formatting right, debugging why the library is not picking up right styling or worse compiling/maintaining dependencies for these libraries. Moreover, making it all work on hosting providers like Heroku is a task in itself.
DocRaptor.com is a nice service to which I can delegate all the heavy lifting of generating documents by using their simple API. Using their service I can be pretty confident in providing exporting functionality to my users without worrying about eating up all the RAM of my server.
Let me show you how to integrate DocRaptor in your Rails application in a few simple steps
Generate a pdf for an invoice using DocRaptor
Let's first add their gem
gem "docraptor"
For demo purpose add a route
root "invoices#show"
then we will generate a config file & mention our API key
DocRaptor.configure do |config|
config.username = "YOUR_API_KEY_HERE"
end
Now we will generate our controller
rails g controller Invoice show
Before we start designing our invoice view. We will drop TailwindCSS CDN code in our "app/views/layouts/application.html.erb". We can now move to designing our view inside "app/views/invoices/show.html.erb"
<main class="w-full mt-20 flex flex-col bg-white rounded p-8 text-lg">
<section class="flex w-full justify-center py-4">
<img src="https://res.cloudinary.com/bilalbudhani/image/upload/v1577093397/muzica_rryfmx.png" class="w-1/3">
</section>
<section class="flex justify-between w-full">
<div class="flex flex-col">
<strong>Invoice #001</strong>
<span class="text-gray-600 mt-4">BILL TO</span>
<span>Docraptor Demo LLC</span>
<span>California, USA</span>
</div>
<div class="flex flex-col">
<strong>Invoice Date: 2020-09-10</strong>
<strong class="mt-8">Status: <span class="text-green-800">PAID</span></strong>
</div>
</section>
<section class="mt-8 w-full">
<table class="w-full">
<thead>
<tr class="border-b border-b-2">
<th class="text-left py-2">Item</th>
<th class="text-left py-2">Unit Cost</th>
<th class="text-left py-2">Quantity</th>
<th class="text-left py-2">Amount</th>
</tr>
</thead>
<tbody>
<tr class="border-b">
<td class="py-4">
Lite Plan Subscription
</td>
<td class="py-4">
$19.00
</td>
<td class="py-4">
1
</td>
<td class="py-4">
$19.00
</td>
</tr>
<tr class="border-b">
<td colspan="2"></td>
<td class="py-4">
Subtotal
</td>
<td class="py-4">
$19.00
</td>
</tr>
<tr class="border-b">
<td colspan="2"></td>
<td class="py-4">
Tax Rate
</td>
<td class="py-4">
0%
</td>
</tr>
<tr class="border-b">
<td colspan="2"></td>
<td class="py-4">
Amount due
</td>
<td class="py-4">
$19.00
</td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="4" class="py-4">
<p>Please write us at <a href="mailto:[email protected]">[email protected]</a> in case of any questions</p>
</td>
</tr>
</tfoot>
</table>
</section>
</main>
This view should look like
We can tweak our view as per need. Once we're done with designing our view. We can move to calling DocRaptor API to generate PDF.
To get the output of the final view contents we will use Rails' "render_to_string" method and pass it to DocRaptor API
class InvoicesController < ApplicationController
def show
docraptor = DocRaptor::DocApi.new
resp = docraptor.create_doc(
test: true,
document_content: render_to_string,
name: "invoice-001.pdf",
document_type: "pdf",
prince_options: {
media: "screen"
}
)
send_data resp, filename: "invoice-001.pdf", type: "application/pdf"
end
end
Rerunning the above code should generate pdf and start downloading in our browser.
Hosted Document Feature
Another great feature of DocRaptor.com is we can ask it to generate & host the document as well for us. This allows us to skip another major step of uploading document to a third party service & save us effort of maintaining uploading code. To use this feature we will use create_hosted_doc method and redirect user to download url
docraptor = DocRaptor::DocApi.new
resp = docraptor.create_hosted_doc(
test: true,
document_content: render_to_string,
name: "invoice-001.pdf",
document_type: "pdf",
prince_options: {
media: "screen"
}
)
# We can save the download URL to a model
redirect_to resp.download_url
Voila! It is just as easy. All the above code is available on Github https://github.com/BilalBudhani/docraptor-rails-demo
Closing thoughts
When James from DocRaptor.com reached out to me to review their service, I jumped on to it as I have experienced the problems of generating documents on my own first hand. I'm quite impressed with this service & its response time, I will plan to start migrating export functionality inside my projects to use this service.