Soli::PDF
The whole public API fits in one module: two render methods, a warnings reader, a binary setter, and four error classes.
require 'soli/pdf'
pdf = Soli::PDF.render(template: template, data: data, title: 'Invoice F-42')
Soli::PDF.render_to_file('invoice.pdf', template: template, data: data)
Soli::PDF.last_warnings # => ["unresolved placeholder: ${invoice.po}"]
Soli::PDF.binary_path = '/opt/render-pdf/render_pdf'
#Soli::PDF.render
Soli::PDF.render(template:, data: nil, invoice: nil, xml: nil, **options) # => String (binary)
Renders a PDF and returns its bytes as a binary String (encoding ASCII-8BIT), ready for File.binwrite, send_data or an upload.
| Argument | Type | Meaning |
|---|---|---|
template: | Hash, Array or String | The layout template. A Hash or Array is serialised with JSON.generate. A String is passed through as JSON text, not as a file path. |
data: | Hash, Array or String | The data document the ${...} placeholders read from. It can be wrapped as { 'data' => {...} } or given bare. |
invoice: | Hash or String | A typed invoice, used instead of data:. The renderer computes the totals and VAT breakdown and embeds a generated EN 16931 XML. See Factur-X. |
xml: | String | A Factur-X CII XML document to embed, used with data:. The output becomes PDF/A-3b. |
**options | title, author, subject, profile, password, owner_password, stationery, attachments, fonts, images. See Render options. |
Argument rules, checked before anything runs. Each one raises ArgumentError:
- exactly one of
data:andinvoice:must be given (give either data: or invoice:); xml:cannot be combined withinvoice:, which generates its own XML;- an option outside the list above is refused (
unknown option(s): …).
# A template kept as a JSON file can be passed as a String, without parsing it.
pdf = Soli::PDF.render(template: File.read('quote.template.json'), data: quote.to_pdf_data)
# Symbol keys are fine too: JSON.generate turns them into strings.
pdf = Soli::PDF.render(template: template, data: { invoice: { number: 'F-42' } })
On success, render also replaces Soli::PDF.last_warnings. On failure it raises; see Errors & warnings.
#Soli::PDF.render_to_file
Soli::PDF.render_to_file(path, **args) # => path
Calls render(**args) and writes the bytes to path with File.binwrite. Returns path. It takes the same keyword arguments as render.
Soli::PDF.render_to_file(Rails.root.join('tmp', "invoice-#{invoice.id}.pdf"),
template: TEMPLATE, data: invoice.to_pdf_data)
#Soli::PDF.last_warnings
Soli::PDF.last_warnings # => Array<String>
The warnings the renderer printed during the last successful render: placeholders with no value, images that could not be loaded, characters that no loaded font covers, invalid barcode data, and so on. It is empty when there were none, and before the first render.
pdf = Soli::PDF.render(template: template, data: data)
Rails.logger.warn("PDF: #{Soli::PDF.last_warnings.join('; ')}") if Soli::PDF.last_warnings.any?
Warning
last_warningsis stored on the module, so all threads share it. In a threaded server (Puma), read it right after your ownrendercall and treat it as best-effort: another thread's render can replace it in between.
#Soli::PDF.binary_path=
Soli::PDF.binary_path = '/opt/render-pdf/render_pdf'
Soli::PDF.binary_path = nil # back to SOLI_PDF_BIN or the downloaded copy
Uses this executable instead of the downloaded one. It takes precedence over the SOLI_PDF_BIN environment variable. The path must point to an executable file. If it doesn't, the next render raises Soli::PDF::BinaryNotFound. See The render_pdf binary.
In a Rails app, set it in an initializer:
# config/initializers/soli_pdf.rb
Soli::PDF.binary_path = ENV['RENDER_PDF_PATH'] if ENV['RENDER_PDF_PATH']
#Soli::PDF::Binary
The class that locates the executable. You rarely need it directly, but it is handy for health checks and build steps.
| Method | Returns |
|---|---|
Binary.path | Absolute path of the executable. Downloads it first if needed. |
Binary.fonts_dir | The fonts/ directory next to the executable, or nil. |
Binary.install_dir | Where the downloaded copy lives: ~/.cache/soli-pdf/<BINARY_VERSION>/render-pdf-<os>-<arch>. |
Binary.artifact | The release asset name for this machine, for example render-pdf-linux-amd64. |
# Fail the deploy early rather than the first customer's download.
Soli::PDF::Binary.path
#Constants
| Constant | Value | Meaning |
|---|---|---|
Soli::PDF::VERSION | "0.1.0" | The gem's version. |
Soli::PDF::BINARY_VERSION | "2.9.0" | The Soli release whose render_pdf assets the gem downloads. |
#Errors
All errors inherit from Soli::PDF::Error, which inherits from StandardError:
| Class | Raised when |
|---|---|
Soli::PDF::BinaryNotFound | The platform is unsupported, or a configured path is not executable. |
Soli::PDF::DownloadError | The release asset could not be fetched or unpacked, or its SHA-256 did not match. |
Soli::PDF::RenderError | render_pdf exited with an error. It has #stderr (the renderer's message) and #status (a Process::Status). |
Errors & warnings shows the messages and how to handle each one.