Guide
Rails
The pdg-rails gem — render PDFs in Rails like HTML, with .pdf.erb views, layouts, and partials.
pdg-rails lets you render PDFs the way you render HTML: write .pdf.erb views
and render them through the normal Action View stack — layouts, partials, helpers,
any template engine — to produce a pdg XML document, which the
pdg gem turns into a PDF.
<%# app/views/layouts/pdf.pdf.erb %>
<document version="2.0">
<config><page size="A4" margin="40px"/></config>
<pages><page><%= yield %></page></pages>
</document>
<%# app/views/invoices/show.pdf.erb %>
<text size="20" bold="true"><%= @invoice.title %></text>
<%= render @invoice.line_items %>
<text>Total: <%= number_to_currency(@invoice.total) %></text>
class InvoicesController < ApplicationController
def show
@invoice = Invoice.find(params[:id])
respond_to do |format|
format.html
format.pdf
end
end
end
GET /invoices/1.pdf now returns a PDF.
Installation
# Gemfile
gem "pdg-rails"
bundle install
This pulls in the pdg gem, which bundles the native engine — no toolchain
needed.
Two ways to render
Both run the view through the full Action View stack.
The :pdf format. Register a .pdf.erb view and let the format do the work:
respond_to { |format| format.pdf }, or simply visit /invoices/1.pdf with no
respond_to block — the implicit render is intercepted when the request format is
:pdf. The download filename defaults to the action (show.pdf) and the
disposition to inline.
render pdf:. For explicit control — a different template, a layout, a
download name:
render pdf: "invoices/show", # template (defaults to the current action)
layout: "pdf", # layout name, or false for none
locals: { invoice: @invoice },
filename: "invoice-#{@invoice.number}.pdf",
disposition: "attachment", # force a download
base: Rails.root.join("app/pdf_assets").to_s
Layouts, partials, helpers
Everything works as it does for HTML:
- Layouts live at
app/views/layouts/<name>.pdf.erband wrap the view with<%= yield %>. Theapplicationlayout is used by default if a.pdfvariant exists; name another withlayout:orPdgRails.config.layout. - Partials render with
render "partial",render @collection, etc. — name them_line_item.pdf.erb. - Helpers and instance variables are all in scope. Any handler works:
show.pdf.haml,show.pdf.slim— it just has to output pdg XML.
The composed document must be valid pdg XML — see the element reference and the other guides.
Assets
Relative paths in the document (<font-face src>, <image src>, <pdf src>)
resolve against base, which defaults to Rails.root. http(s) URLs and
<google-font> faces are fetched by the engine regardless.
Errors
A failed render raises from the engine gem: PDG::RenderError when the document
is withheld (a strict-mode block or a fatal parse/layout error), carrying
#diagnostics. Unhandled, it surfaces as a 500 like any controller exception —
rescue it to report the diagnostics or render a fallback.
rescue_from PDG::RenderError do |e|
Rails.logger.error(e.message) # includes each diagnostic
head :unprocessable_entity
end
Configuration
# config/initializers/pdg.rb
PdgRails.configure do |c|
c.layout = "pdf" # default layout for PDF views (nil = Rails default)
c.disposition = "inline" # "inline" or "attachment"
c.base = Rails.root.join("app/pdf_assets").to_s
c.intercept_format = true # auto-render the :pdf format; false = require `render pdf:`
end