はじめに
本記事は オリジナルアプリ Kiyoraの続編となります。
プログラミングスクールで作成したオリジナルアプリケーションで作成した
Ruby on Railsでのpdf出力について取り上げます。
実行環境
rails 6.0.3
ruby 3.0.1
psql (PostgreSQL) 14.2
前提
rails newでアプリ作成
rails db:create を実行済み。
prawnの導入
gemファイルに以下を追加します。
テーブルも表示させたいのでprawn-tableもインストールします。
gem 'prawn'
gem 'prawn-table'
実行コマンド
bundle install
モデル作成
rails g model invoice_pdf
コントローラーを作成
rails g controller invoice_pdfs
ルーティングの設定
showの画面でPDFを表示
resources :invoice_pdfs, only: %i[show]
pdfを実装させる
class InvoicePdf < Prawn::Document
FONT_PATH = Rails.root + '/Users/workspace/kiyora/app/assets/fonts/ipaexg.ttf'
def initialize(record,customer)
super(
page_size: 'A4',
top_margin: 40,
bottom_margin: 30,
left_margin: 20,
right_margin: 20
)
@record = record
@customer = customer
font 'app/assets/fonts/ipaexg.ttf'
header
move_down 50
contents
end
# コンポーネント作成
def header
text '請求書', size: 20, align: :center
move_down 20
text "作成日: #{Date.today}",align: :right, size: 10
text "株式会社 良好建築設備",align: :right, size: 10
text "住所 東京都台東区花川戸3丁目1-1-1",align: :right, size: 10
text "電話: 03-333-3333",align: :right, size: 10
text "info: contact@center.com",align: :right, size: 10
image 'app/assets/images/sqe_rei.jpeg',align: :right, width: 40, height: 40,at: [400, 700]
text "#{@customer.name} 様",align: :left, size: 12
text "郵便番号: #{@customer.zip} ",align: :left, size: 12
text "住所: #{@customer.address} ",align: :left, size: 12
end
def contents
move_down 10
text "作業日:#{@record.support_at.strftime("%Y年%m月%d日").to_s}"
text '下記の通りご請求申し上げます。',align: :center
bounding_box([0, 555], width: 310, height: 65) do
move_down 10
text "合計金額 #{@record.sales+(@record.sales*0.1).round}", size: 16, align: :left
end
rows = [['詳細', '数量', '単価', '金額'],
["#{@record.category}", '1',"#{@record.sales}", "#{@record.sales+(@record.sales*0.1).round}"]
]
#テーブルの作成。カラムが4つ。それぞれの幅を指定。
table(rows, column_widths: [370, 30, 60, 60], position: :center) do |table|
table.cells.size = 10
table.row(0).align = :center
end
bounding_box([373, 300], width: 150, height: 100) do
table [['小計', "#{@record.sales}"], ['消費税', "#{(@record.sales*0.1).round}"],
['合計金額', "#{@record.sales+(@record.sales*0.1).round}"]],
column_widths: [50, 100], position: :right do |table|
table.cells.size = 10
end
move_down 10
text "お振込期日 #{Date.today+14}", size: 12, align: :left
end
end
end
フォントのダウンロード
クラス名にはPrawn::Documentを継承させます。
フォントをダウンロードします。prawnは日本語には対応していない為。
こちらのページからダウンロード。
ダウンロードしたファイルを /app/assets/fonts以下に配置。
コードの説明
def initialize
pdfには顧客情報に紐づいた情報とタスク情報を出力したいので
(下記に説明あり)
def initialize(record,customer)と記述。
superで外枠となるサイズを指定。
引数にrecord customerを設定。
@record = Task.find(params[:id])
@customer = @customers.find_by(task_id: @record.id)
コントローラーファイルで上記をあらかじめ設定し、recordにはTaskモデル、
customerにはcustomerモデルの情報が格納される。
move_down 50
headerとcontentsの間にどれくらい余白を入れるかmove_downによって数値設定。
値が大きいほど、空間ができる
名前の表示
text "#{@customer.name} 様",align: :left, size: 12
@customerのnameカラムに入っている情報を取得したい場合、"#{}"で展開させる。
sizeはフォントサイズのこと
bounding_box([0, 555], width: 310, height: 65)
pdfの中にボックスを作成します。始点となる座標点を指定します。
[横, 縦]、単位はポイント(pt)になります。そこから、幅310高さ65のボックスを作ります。
公式ドキュメント
table(rows, column_widths: [370, 30, 60, 60], position: :center) do |table|
table.cells.size = 10
table.row(0).align = :center
end
セルのサイズと文字の大きさ
table.cells.size = 10
枠線を特定箇所のみ付けることも可能。
table.cells.borders = %i[right top]
今日の請求書発行日から14日後に日付を設定。
text "お振込期日 #{Date.today+14}", size: 12, align: :left
コントローラーファイル
class InvoicePdfsController < ApplicationController
def show
@records = Task.all # pdf上で使用するレコードのインスタンスを作成
@record = Task.find(params[:id])
@customers = Customer.all
@customer = @customers.find_by(task_id: @record.id)
respond_to do |format|
format.html
format.pdf do
# pdfを新規作成。引数にインスタンス変数を渡す。
pdf = InvoicePdf.new(@record, @customer)
send_data pdf.render,
filename: "invoice.pdf",
type: "application/pdf",
disposition: "inline" # 画面に表示。外すとダウンロードされる。
end
end
end
private
def set_show
params.permit(:name,:dispatch,
properties_attributes:[:name, :zip, :prefecture, :city , :address, :tel,:_destroy ],
partners_attributes:[{id:[]},:name,:worker,:contact,:sales,:_destroy],
agents_attributes:[:id,:manager_name, :name, :zip, :prefecture, :city, :address,:_destroy],
customer_attributes:[:id,:name,:zip,:address,:tel,:_destroy]
)
end
end
新規作成を行う。
pdf = InvoicePdf.new(@record, @customer)
disposition: "inline"
PDFをブラウザ上に出力する際に必要なオプション。外すとダウンロードになる。
他にもprawnには図形を出力したりする機能もあり、公式ドキュメントを見ると
利用用途が広がりそうです。
ブラウザでの表示
PDF版マニュアル
参考にさせて頂いた記事
https://techtechmedia.com/prawn-pdf-rails/
https://qiita.com/yacci/items/61a26ddd3f6eb2494121
https://qiita.com/ayies128/items/7262b771fdae5b7f0098
エンジニアのスタートラインにようやく立てたところです。
未熟な点が多々あるかとは思いますが、温かく見守って頂ければと思います。