Generating barcode PDFs with Rails

For a project, I was researching methods to generate individual PDFs with imprinted EAN barcodes. Some of the how-tos and blog articles I found were quite old, and it was not directly obvious if the solution still works and can be recommended in 2023. The following represents my short note-taking of a decent way to do this. There may be other or better ways, but this one works for me.

Barby is a barcode generator library for Ruby. It generates a barcode as an image or as a PDF. For creating the actual PDF with background image I am using the Prawn PDF generation library for Ruby. It produces PDFs from scratch and annotates existing PDFs with text, images, and barcodes.

I am using two model classes, one for the voucher with the code property (which shall be printed as a barcode), and one for the PDF generation. The PDF generation class is a subclass of Prawn::Document. It takes a path and a code as arguments and generates a PDF with the barcode imprinted. The voucher class creates a temporary file, calls the PDF generation class, and returns the path to the temporary file. As we are using Rails Tempfile, the temporary file is deleted automatically when the Rails process exits.

The resulting PDF should be 100mm x 133mm with a png as the background image. At first, I experimented with the background option of Prawn::Document, but this did not work as expected. The background image didn’t scale to the page size. Instead, I am using the image method to draw the background image. The fit option scales the image to the page size.

Prawn’s measurement_extensions allow the use of mm as a unit for the page size instead of the default 1/72 inch.

require "barby/barcode/code_128"
require "barby/outputter/prawn_outputter"
require "prawn/measurement_extensions"

class CodePdf < Prawn::Document
  def initialize path, code, background
      page_size: [,],
      margin: 0

    image background, fit: [,]
    barcode code
    render_file path

  def barcode code
    barcode = code
    barcode.annotate_pdf self, height:, x:, y:

In the code class, we create a temporary file and call the PDF generation class. The background image is found in the app/assets/images/{language} directory. The name of the background image is stored in the voucher property of the price object (where the code belongs_to). The voucher property is a string like voucher.png. The I18n.locale method returns the current locale, e.g. de or fr which is used to find the correct background image.

def voucher
  # Create temporary file e.g. tmp/voucher20230805-66997-kozjms.pdf
  tmpfile = "voucher", Rails.root.join("tmp")
  path = tmpfile.path + ".pdf"
  bg_path = Rails.root.join "app", "assets", "images", I18n.locale.to_s, price.voucher path, code, bg_path

Here is an example of the resulting voucher PDF with the barcode imprinted:

PDF with barcode