Rails prawnを用いたPDF生成
こんにちは。HANOWAエンジニアの佐々木です。
今回は結構前ですが、HANOWAでprawnというgemを用いてRailsにてPDFを生成する機能を実装したので、そちらについてお話しさせていただきます。
以前公開した、AIを活用して開発効率を上げる(ChatGPT、GithubCopilot)で少し話にあげているのでこちらの記事ももしよろしければ見て頂ければと思います。
Prawnとは
PDF生成ができるgemです。なぜなのかは把握してませんが意味はエビ🦐らしいです。
他にもPDFを生成するgemはいくつかありますが、PrawnはコードでPDFを生成するタイプのためかなり細かい作り込みが可能になります。
HANOWAではもともとフロント側でPDF生成を行なっておりました。HTML、CSSで作成したものをPDF化するという感じです。フロントで行うと処理が重くなってしまいますし、テクニカルな処理は極力サーバーサイド側で行いたいという意向があり、Prawnを用いてRails側でPDF生成を行う決断をしました。
私はフロントエンド出身なので、少し慣れるまでに時間がかかりましたが記事も充実しているので、案外なんとかなりました。
導入
gem 'prawn'
gem 'prawn-table'
まずはgemを追加します。prawn-tableというのはテーブルを作成するのに使用するので、一緒に入れておくことをお勧めします。
controller
コントローラーに直接、PDFを作成するコマンドを書き込んでも良いのですが、長くなることが多いため可読性や保守性の観点から別途クラスを作成して管理することにしました。
class Api::GenerateResumePdfController
# 履歴書PDFを生成する
def resume_pdf_data
pdf_content_params = {
name: 'sample name',
address: '大阪府大阪市...',
phone_num: '090-1234-5678',
}
pdf = ResumePdf.new(pdf_content_params)
send_pdf(pdf, "resume.pdf")
end
end
こんな感じでコントローラーはかなりシンプルになりました。PDF生成に使用するパラメータは今回はサンプルなので直接記載していますが、別途サービスクラスを作るかシリアライザーなどで必要な情報だけ渡すようにするのが良いと思います。
PDF生成クラス
class ResumePdf < Prawn::Document
def initialize(params)
super(
page_size: 'A4',
top_margin: 40,
bottom_margin: 30,
left_margin: 20,
right_margin: 20
)
# 日本語フォント
font "app/assets/fonts/ipaexm.ttf"
text "#{params[:name]}", size: 12
text "#{params[:address]}", size: 16
text "#{params[:phone_num]}", size: 20
end
end
super内でページのサイズや上下左右のマージン等を設定できます。page_sizeについてはA4やB3のような指定方法とpage_size: [1024, 512]のようなサイズ指定も可能です。
デフォルトで日本語対応していないので、別途使用したいフォントをダウンロードしておく必要があります。(著作権は気をつけましょう)
実際に表示される内容は以下のようになります。
渡したパラメータが正しく表示されていますね。
次はテーブルを用いた実装を試してみましょう。履歴書PDFを生成するクラスを想定しているので少しそれっぽくしてみます。
// controller
class Api::V1::GeneratePdfController < Api::BaseController
# 履歴書PDFを生成する
def resume_pdf_data
pdf_content_params = {
name: 'HANOWA太郎',
name_kana: 'ハノワタロウ',
address: '大阪府大阪市...',
phone_num: '090-1234-5678',
birthdate: '1990年1月1日',
email: 'sample@hanowa.co.jp',
today: Time.zone.today.strftime("%Y年%m月%d日"),
}
pdf = ResumePdf.new(pdf_content_params)
send_pdf(pdf, "resume.pdf")
end
// PDF生成クラス
class ResumePdf < Prawn::Document
def initialize(params)
super(
page_size: 'A4',
top_margin: 40,
bottom_margin: 30,
left_margin: 20,
right_margin: 20
)
stroke_axis
# 日本語フォント
font "app/assets/fonts/ipaexm.ttf"
@params = params
# contents
header
move_down 35
table_basic_info
end
private
def header
text_box "履歴書", size: 18, at: [0, 770], valign: :bottom, height: 30
indent(420) do
text_box "#{@params[:today]}現在", size: 10, at: [0, 770], valign: :bottom, height: 30
end
end
def table_basic_info
base_table = [
["フリガナ", @params[:name_kana]],
["氏名", @params[:name]],
["生年月日", @params[:birthdate]],
["連絡先", @params[:address]],
["電話番号", @params[:phone_num]],
["E-mail", @params[:email]]
]
table base_table,
column_widths: [50, 460] do
cells.size = 10
end
end
end
少しだけそれっぽくできたでしょうか。
パラメータも増やして、テーブルを生成する記載を追加しました。
可読性を上げるために各パーツごとにプライベートメソッドに切り出しています。
stroke_axisという記載を追加していますが、これは左側と下側についたメモリを表示する設定です。最終的には外しますが、実装中はmove_down 35のように座標をもとに位置指定をする必要があるため表示しておくとわかりやすいです。
まとめ
今回はPrawnを用いたRailsでのPDF生成方法を紹介いたしました。
もっとカスタマイズすることも可能なので、要件が細かいPDF生成が必要な際には活用できると思います。
英語で量もかなり多いですが、公式マニュアルもあるのでこちらも参考にしていただければと思います!
HANOWAでは他のメンバーもnoteを書いているので、ぜひ見に行ってみてください!
この記事が気に入ったらサポートをしてみませんか?