今回はRailsでPDF出力を実装することができるGem「Prawn」について解説したいと思います。Web上でデータをPDF化して出力したい、PDFを商品として扱いたい、取引先がPDFを要求してきたなど、PDF化の需要は案外高いのではないでしょうか。PDF出力実装で悩んでいる方の参考になればと思います。
RailsにおけるPDF出力実装
RailsにおけるPDF出力が実装できるライブラリは主には以下の3つです。
- wicked_pdf
- PDFKit
- Prawn
これらそれぞれの特徴を簡単にまとめると以下のようになります。
カスタマイズ性 | 開発コスト | 特徴 | |
wicked_pdf | 低い | 低い | HTMLをPDFに変換 |
PDFKit | 低い | 低い | HTMLをPDFに変換 |
Prawn | 高い | 高い | RubyをPDFに変換 |
参考: Excelで作成していた請求書を、Railsで自動作成できるようにした話
上記の表からも分かる通り、PrawnはRubyをPDFに変換し出力を行うためRubyエンジニアにとって比較的扱いやすいライブラリになっています。
Prawnとは
PrawnとはPDF出力機能を簡単に実装することができるgemです。
Prawnはpure Rubyで実装することができ、カスタマイズも多様であるため、RailsでPDF出力を実装する際の第一候補であるということができます。

Prawnを用いた実装手順
では実際にPrawnを用いたPDF出力を実装してみましょう。
アプリケーションの作成
まずはrails newを実行し、新規アプリケーションを立ち上げます。
% rails new prawn-app -d mysql
アプリケーション名: prawn-app
Rails: 6.0.3.5
Ruby: 2.6.5
データベース: MySQL
データベースの作成
次にデータベースを作成しましょう。
% rails db:create
Created database 'prawn_app_development'
Created database 'prawn_app_test'
Prawnの導入
続いてはPrawnの導入です。
Gemfileにprawnとprawn-tableを記述し、bundle installを実行しましょう。
gem 'prawn'
gem 'prawn-table'
% bundle install
コントローラの導入
次にpost_pdf_controller.rbを作成します。
rails gコマンドでコントローラを作成しようとすると、不要なファイルが生成されてしまうため、エディタ上で直接作成しましょう。
ディレクトリ構成
app
- controllers
- application_controller.rb
- post_pdf_controller.rb
# post_pdf_controller.rb
class PostPdfController < ApplicationController
def index
end
end
ルーティングの編集
では、先程作成したpost_pdf_controller.rbのindexアクションに向けたルーティングを作成しましょう。
# routes.rb
Rails.application.routes.draw do
resources :post_pdf, only: :index
end
途中経過
ここで一旦サーバーを立ち上げ、状態を確認してみます。
「localhost:3000/post_pdf」にアクセスし、missing a templateエラーが吐かれれば正常な挙動と言えます。

PDFの作成
ではここから本題のPDF出力処理の実装を行っていきましょう。
まずはPDFを作成するクラスをlib直下に作成します。
ディレクトリ構成
lib
- pdf
- practice_pdf
- post_pdf.rb
- practice_pdf.rb
作成したpractice_pdf.rbとpost_pdf.rbに以下の記述をそれぞれ貼り付けましょう。
# lib/pdf/practice_pdf.rb
module PracticePdf
end
# lib/pdf/practice_pdf/post_pdf.rb
module PracticePdf
class PostPdf < Prawn::Document
def initialize
super(page_size: 'A4') # 新規PDF作成
stroke_axis # 座標を表示
end
end
end
それぞれのコードを順番に見ていきます。
まずpost_pdf.rbはPDF出力を担うメインファイルになるため、このファイルにPrawn::Documentを継承させています。
次にPostPdfクラスのinitializeメソッドでsuperを実行することにより、Prawn::Documentのinitializeメソッドが実行されます。それにより、A4サイズ白紙のPDFが生成されるようになります。

stroke_axisはPDFの座標を表示する際に必要なオプションです。
application.rbの設定
先ほどlib直下にPDF出力を担うファイル群を作成しましたが、そのままでは正常に読み込みが行われません。
config/application.rbに以下の記述を追記し、lib直下のファイル群の読み込みが行われるように設定しましょう。
# config/application.rb
require_relative 'boot'
require 'rails/all'
# Require the gems listed in Gemfile, including any gems
# you've limited to :test, :development, or :production.
Bundler.require(*Rails.groups)
module PrawnApp
class Application < Rails::Application
# Initialize configuration defaults for originally generated Rails version.
config.load_defaults 6.0
# Settings in config/environments/* take precedence over those specified here.
# Application configuration can go into files in config/initializers
# -- all .rb files in that directory are automatically loaded after loading
# the framework and any gems in your application.
# 以下の記述を追記
config.eager_load_paths += %W(#{Rails.root}/lib/pdf)
end
end
コントローラの編集
ここまでの作業でPDFを作成する処理の実装ができました。
ここでは実際に作成したPDFの出力を行う実装を行っていきます。
post_pdf_controller.rbを以下のように編集しましょう。
# post_pdf_controller.rb
class PostPdfController < ApplicationController
def index
respond_to do |format|
format.pdf do
post_pdf = PracticePdf::PostPdf.new().render
send_data post_pdf,
filename: 'post_pdf.pdf',
type: 'application/pdf',
disposition: 'inline' # 外すとダウンロード
end
end
end
end
順番に見ていきます。
まずは「format.pdf do」の記述によりpdf形式での出力処理をdo~end間で行います。
続いてPracticePdf::PostPdf.new().renderでインスタンスの生成を行い、その出力準備を行っています。
send_data以下はPDF出力に必要なオプションになるため、そのまま使用しましょう。(ファイル名は適宜変更してください)
disposition: ‘inline’はPDFをブラウザ上に出力する際に必要なオプションになります。この記述を外すことにより、出力ではなくPDFのダウンロードが行われます。
動作確認
ではサーバーを再起動し「localhost:3000/post_pdf.pdf」にアクセスしてみましょう。
以下のように、座標のみが表示された白紙のPDFが表示されれば成功です。

リンクからPDF画面へ遷移
現在のままでは、直接「localhost:3000/post_pdf.pdf」とURLを打ち込まなければPDFを表示させることができません。
ここではリンクからPDFを表示できるように実装してみましょう。
まずはroutes.rbを編集し「localhost:3000/post_pdf」をrootパスに設定します。
Rails.application.routes.draw do
root 'post_pdf#index'
end
続いてviews以下にpost_pdfフォルダを作成し、その直下にindex.html.erbを配置します。index.html.erbには以下の記述を追記しましょう。
ディレクトリ構成
app
- views
- layouts
- appliacation.html.erb
- mailer.html.erb
- mailer.text.erb
- post_pdf
- index.html.erb
# app/views/post_pdf/index.html.erb
<%= link_to "PDFを表示", root_path(format: "pdf") %>
サーバーを再起動し、以下のようにリンクからPDFが表示されれば成功です。
PDFのカスタマイズ
ここからはPDFのカスタマイズについて見ていきましょう。
文字の配置
PDF上に文字を配置するにはtext_boxオプションを使用することで実現できます。
lib/pdf/practice_pdf/post_pdf.rbを以下の記述に変更しましょう。
module PracticePdf
class PostPdf < Prawn::Document
def initialize
# 新規PDF作成
super(page_size: 'A4')
# 座標を表示
stroke_axis
header
end
def header
text_box 'ヘッダー'
end
end
end
しかしこのままPDFを開こうとすると下記画像のようなエラーが吐かれてしまいます。

こちらのエラーはフォントを指定してあげることで解消することができます。
まずは以下のリンクからフォントをダウンロードしましょう。
↓ ↓ ↓

続いてapp/assets以下にfontsフォルダを作成します。
fontsフォルダには先程ダウンロードしたフォントを配置しましょう。

全てのフォントを表示するため、post_pdf.rbの記述も以下のように変更します。
module PracticePdf
class PostPdf < Prawn::Document
def initialize
# 新規PDF作成
super(page_size: 'A4')
# 座標を表示
stroke_axis
header
end
def header
font FONT
text_box 'ヘッダー'
font FONT_BOLD
text_box 'ヘッダー', at: [0, 730], size: 10
font FONT_EXTRALIGHT
text_box 'ヘッダー', at: [0, 700], size: 20
font FONT_HEAVY
text_box 'ヘッダー', at: [0, 650], size: 30
font FONT_LIGHT
text_box 'ヘッダー', at: [0, 600], size: 40
font FONT_MEDIUM
text_box 'ヘッダー', at: [0, 550], size: 50
font FONT_NORMAL
text_box 'ヘッダー', at: [0, 500], size: 60
end
end
end
サーバーを再起動し、PDFを開いてみましょう。
以下のようにフォントとサイズが異なる文字が配置されたかと思います。

テーブルの配置
テーブルを配置するにはtableオプションを使用し、二次元配列でテーブル構成を記述する必要があります。
post_pdf.rbを以下のように変更してみましょう。
module PracticePdf
class PostPdf < Prawn::Document
def initialize
# 新規PDF作成
super(page_size: 'A4')
# 座標を表示
stroke_axis
cols = [
['banana', 'apple', 'peach'],
['kiwi', 'grape', ''],
['cherry', 'watermelon', '']
]
table cols
end
end
end
サーバーを再起動し、PDFを開くと以下のようなテーブルが表示されるかと思います。

画像の表示
最後にPDF上に画像を表示させてみましょう。
画像はimageオプションを使用することで実装が可能です。
まずは適当な画像をapp/assets/images以下に配置しましょう。

post_pdf.rbを以下のように編集しましょう。
module PracticePdf
class PostPdf < Prawn::Document
def initialize
# 新規PDF作成
super(page_size: 'A4')
# 座標を表示
stroke_axis
image 'app/assets/images/sample.jpeg', at: [10, 200]
end
end
end
サーバーを再起動し、再度PDFを開いてみましょう。
以下のように、assets/images直下に配置した画像が表示されているはずです。

まとめ
- 代表的なPDF出力を実装するライブラリはwicked_pdf、PDFKit、Prawnの3種類
- PrawnとはPDF出力機能を簡単に実装することができるgem
- Prawnはpure Rubyで実装することができ、カスタマイズも容易
- 文字の配置にはtext_boxオプションを使用する
- テーブルの配置にはtableオプションを使用する
- 画像の配置にはimageオプションを使用する
参考
- Excelで作成していた請求書を、Railsで自動作成できるようにした話
- 【Railsエンジニア必見】PDF出力するPrawnを使ってみた
- Rails(Ruby)でPDFを作成する方法 基礎編
- Rails5でPrawnによるPDFを作成する
- Rails prawnを使ってPDFを作成する
今回はRailsでPDF出力を実装することができるGem「Prawn」について解説しました。PDF出力を実装する機会は多くはないかもしれませんが、必要になった際の参考になればと思います。