A common way to generate PDF from HTML with Ruby is using wicked_pdf or pdfkit gems, but they rely on an external executable and it’s slow compared to native methods. So creating PDF documents is often delegated to background jobs.
To offer an alternative, years ago I started to work on a project based on Prawn PDF (prawn-styled-text) to create PDF files starting from simplified HTML. Recently I decided to rewrite it from scratch to improve the rendering with prawn-html.
A simple controller’s action to generate PDF files
Here is a plain simple example:
class SomeController < ApplicationController
def sample_action
respond_to do |format|
format.pdf do
pdf = Prawn::Document.new
PrawnHtml.append_html(pdf, '<h1 style="text-align: center">A test</h1>')
send_data(pdf.render, filename: 'sample.pdf', type: 'application/pdf')
end
end
end
end
Setup an action controller renderer for PDFs
Another approach is to prepare a Renderer responsible for serving the PDF views:
# config/initializers/renderers.rb
ActionController::Renderers.add :pdf do |pdf_options, _context_options|
pdf = Prawn::Document.new(pdf_options)
PrawnHtml.append_html(pdf, render_to_string)
send_data(pdf.render, type: Mime[:pdf])
end
So the controller’s action can be:
# some controller
def sample_action
respond_to do |format|
format.html
format.pdf do
render pdf: { page_size: 'A4' }
end
end
end
And we can use a single view to offer both the preview and the PDF:
<!-- app/views/some/sample_action.erb -->
<h1>The dolphins</h1>
<div>
<em>“For instance, on the planet Earth, man had always assumed that he was
more intelligent than dolphins because he had achieved so much—the wheel, New
York, wars and so on—whilst all the dolphins had ever done was muck about in
the water having a good time. But conversely, the dolphins had always believed
that they were far more intelligent than man—for precisely the same reasons.”
</em> — Douglas Adams, <strong>The Hitchhiker's Guide to the Galaxy</strong>
</div>
With older Rails versions it’s also necessary to register the Mime type:
# config/initializers/mime_types.rb
Mime::Type.register 'application/pdf', :pdf
That’s it.
Conclusion
Rendering HTML to PDF documents properly is not an easy task and my project supports a limited set of HTML tags and CSS attributes, but sometimes it can be useful to be able to create PDF files from HTML with better performances.
If you are curious, take a look at prawn-html, any feedback is appreciated.