pdf libraries

pdf libraries

Ruby on rails

Ruby on rails

How to Generate PDF files on Ruby on Rails Using Prawn

Marcelo Abreu, founder of pdforge

Marcelo | Founder

Marcelo | Founder

Oct 29, 2024

Oct 29, 2024

Introduction to PDF Generation in Ruby on Rails with Prawn

Prawn, a powerful PDF library for Ruby, makes it possible to create PDF files with a rich variety of elements, providing a high degree of customization for specific document layouts. This is especially valuable for SaaS applications, where dynamically generated PDF reports are common.

You can check out their full documentation here.

Comparison Between Prawn and Other Ruby PDF Libraries

Number of downloads from bestgems of prawn

Other PDF libraries like HexaPDF, WickedPDF, PDFKit, and Grover are also popular in the Ruby community, each with its strengths:

HexaPDF: Pure Ruby library for full PDF manipulation; ideal for in-depth customization, encryption, and annotations.

WickedPDF & PDFKit: HTML-to-PDF conversion using wkhtmltopdf; best for rendering static HTML templates with minimal configuration.

Grover & Puppeteer-Ruby: Chrome-based rendering with JavaScript support; suited for complex layouts and interactive content in PDFs.

In contrast, Prawn focuses on giving you complete control over document layout from scratch, making it perfect for those who need pixel-perfect design.

Guide to generate pdf from html using Ruby on rails prawnPDF
Guide to generate pdf from html using Ruby on rails prawnPDF

Getting Started with Prawn for PDF Creation

Installing and Configuring Prawn for Ruby on Rails

To begin using Prawn, add it to your Gemfile and run bundle install. Once installed, Prawn can be used across Rails controllers or service objects:

# In your Gemfile
gem 'prawn'

# Run this to install
$ bundle install

With Prawn configured, you can call it within a controller or service object to create PDFs on demand.

Understanding Basic Prawn Syntax and PDF Structure

Prawn’s syntax is intuitive, using commands like text, image, and table to build PDF documents. A basic PDF layout in Prawn might look like this:

Prawn::Document.generate("example.pdf") do |pdf|
  pdf.text "Welcome to Prawn PDF Generation"
  pdf.image "/path/to/image.jpg", width: 100, height: 100
end

This code creates a simple PDF with text and an image, providing a foundation for more complex layouts.

Essential Prawn Methods for Text, Images, and Tables

To build out your documents, Prawn offers powerful methods for handling text, images, and tables:

Prawn::Document.generate("example.pdf") do |pdf|
  pdf.text "Invoice Report", size: 24, style: :bold
  pdf.text "Customer: John Doe", size: 14
  
  pdf.image "/path/to/logo.jpg", position: :center, width: 100, height: 50
  
  data = [["Item", "Quantity", "Price"], ["Widget", 2, "$20"], ["Gadget", 1, "$15"]]
  pdf.table(data, header: true)
end

This sample adds an invoice header, an image, and a table with headers, showcasing Prawn’s capacity for structured data layouts.

Styling and Formatting: Fonts, Colors, and Layouts

With Prawn, you control fonts, colors, and positioning, allowing fine-tuned customization. Here’s how to style text and elements:

Prawn::Document.generate("styled_example.pdf") do |pdf|
  pdf.font "Helvetica"
  pdf.fill_color "0096D6"
  pdf.text "Styled Invoice", size: 20, align: :center
  pdf.stroke_color "FF0000"
  pdf.stroke_horizontal_rule
end

This styling provides branding consistency, enhancing the document’s professional appearance.

Generating PDFs from HTML in Ruby on Rails

Creating a Complete Invoice HTML/CSS File as an Example

Start with a simple HTML file for an invoice template. This example will then be used to generate PDF files dynamically.

<!-- invoice.html.erb -->
<div class="invoice">
  <h1>Invoice Report</h1>
  <p>Customer: John Doe</p>
  <table>
    <thead><tr><th>Item</th><th>Quantity</th><th>Price</th></tr></thead>
    <tbody>
      <tr><td>Widget</td><td>2</td><td>$20</td></tr>
      <tr><td>Gadget</td><td>1</td><td>$15</td></tr>
    </tbody>
  </table>
</div>

Include CSS to style the HTML, ensuring it resembles the final PDF’s layout and appearance.

Creating the Invoice Example Using Prawn Methods

Using the HTML structure, recreate the invoice in Prawn to maintain layout consistency:

Prawn::Document.generate("invoice.pdf") do |pdf|
  pdf.text "Invoice Report", size: 20, style: :bold
  pdf.text "Customer: John Doe", size: 14
  
  items = [["Item", "Quantity", "Price"], ["Widget", 2, "$20"], ["Gadget", 1, "$15"]]
  pdf.table(items, header: true)
end

Integrating HTML Templates for Dynamic PDF Content

Dynamic content, such as variable customer information or item lists, can be integrated by passing data from the Rails controller:

# invoices_controller.rb
def show
  customer = Customer.find(params[:id])
  Prawn::Document.generate("invoice_#{customer.id}.pdf") do |pdf|
    pdf.text "Invoice for #{customer.name}"
  end
end

This integration allows flexible content generation directly from Rails models.

Using Prawn with Rails Views: Rendering HTML to PDF

Rendering an HTML view as a PDF in Rails involves generating HTML content, converting it, and applying Prawn’s PDF methods to structure it:

# invoices_controller.rb
def download_invoice
  respond_to do |format|
    format.html
    format.pdf do
      render pdf: "invoice",
             template: "invoices/show.html.erb",
             layout: 'pdf'
    end
  end
end

Adding Page Numbers, Headers, and Footers

Adding elements like page numbers enhances readability. With Prawn, footers and headers are easy to implement:

Prawn::Document.generate("invoice.pdf") do |pdf|
  pdf.number_pages "<page> of <total>", at: [pdf.bounds.right - 50, 0]
end

Creating Interactive Elements: Links and Buttons

Prawn supports clickable links for a more interactive PDF experience. Here’s how to add a link:

pdf.text "Visit our website", link: "https://example.com"

How to Use a PDF API to Automate PDF Creation at Scale

For SaaS platforms, automating PDF generation at scale might require offloading the heavy lifting to a PDF API.

It's also an option to integrate with third-party APIs like pdforge you can handle high-volume PDF generation, complex formatting, and post-processing, all from a single backend call.

Here’s an example of how to integrate pdforge in Rails to convert HTML content into a PDF via an API call:

require 'net/http'
require 'json'
require 'uri'

class PdfApiService
  def self.generate_pdf(html_content)
    uri = URI("https://api.pdforge.com/v1/pdf/sync")
    http = Net::HTTP.new(uri.host, uri.port)
    http.use_ssl = true
    request = Net::HTTP::Post.new(uri.path, {
      'Content-Type' => 'application/json',
      'Authorization' => "Bearer your-api-key"
    })
    request.body = {
      templateId: 'your-template',
      data: { html: html_content }
    }.to_json
    response = http.request(request)
    response.body if response.is_a?(Net::HTTPSuccess)
  end
end

Conclusion

For complete control over PDF layout, Prawn is an excellent tool in Ruby on Rails, particularly when fine-tuning and complex designs are needed.

When simpler HTML-to-PDF conversion suffices, consider alternatives like WickedPDF or PDFkit.

In high-volume scenarios, a third-party PDF API solution like pdforge provides reliable, scalable performance that balances quality with server load.

Generating pdfs at scale can be quite complicated!

Generating pdfs at scale can be quite complicated!

We take care of all of this, so you focus on what trully matters on your Product!

We take care of all of this, so you focus on what trully matters on your Product!

Try for free

7-day free trial

Table of contents

Title