チョムリアップスオ
私はカンボジアでITを教えているエンジニアです。
前回に引き続きまして、今回は、
「生徒IDカードを印刷するアプリ作ってっていわれた話 ~どうやって印刷する?~」
をお送りします!
実際には、どうやって印刷する?っていうか、どうやって印刷するものを出力する?のお話です![]()
表裏印刷のIDカードを印刷するには?
レイアウトがめちゃ重視されてるけどどうする?
開発し始めて、まず一番最初に取り掛かったのは、IDカードの印刷機能です。
十うん年前に新人の時に先輩から言われた
「一番難しいところからやりなさい」
これをモットーにしているからです。
ひとまず、IDカードのデザインは決まっているかどうか質問したところ、
「この通りに作って!」
とカードデザインのPDFが送られてきました。
既定のカードホルダーにぴったり入るように、縦横幅の指定がされています。そして、表面はバイカラーで上下の帯部分があり、生徒の写真、生徒の情報の部分には公印の透過画像が配置され、スタンプを押したようなイメージとなっています。裏面は、学校を管轄する省庁のロゴの下に、学校の情報が書いてあるような感じです。
サイズ、位置、文字フォントなど、細かな調整がきっちりできる方法でなければならないなと思い、ひとまずHTMLとCSSでデザインPDFの通りに作成できるか試すことから始めました。
カードの寸法と帯の幅、写真のサイズと位置をChatGPTにぶっ込んで、ベースを作った後、デザインに近いクメール語のフォントを探しつつ、カードに必要な公印やロゴの画像ファイルももらえたので、それほど苦労することなく、デザイン通りに作ることができました。
アプリでの PDF 生成方法の選定
HTMLとCSSでデザイン通りにIDカードを作成できたので、次は、RubyonRails で PDF を崩れることなく出力することができれば、もうできたようなもんです。
HTML/CSSのテンプレートを元にPDF出力できるGemを探しましたら
- WickedPDF
- Ferrum
- Grover
あたりが出てきました。
先人たちのブログを拝見しましたら、WickedPDFが依存しているHTMLからPDFに変換するためのCLIツールが開発終了を迎えており、Rails7以上では動かないという話が載っていました。今回は最新のRails8で作りたかったため、導入が簡単という評価のあるWickedPDFでしたが、こちらは候補から外しました。
さて残ったのは Ferrum と Grover。いずれも chromium というGoogleが提供するオープンソースのコードベースを用いて、HTML/CSSからPDFを描画します。Groverはchromiumを動かすのに、puppeteer というNode.js製のライブラリを使っており、Ferrumの方が依存関係やNodeを使う分のメモリが少なく済むのがメリットでした。けれども、両者の導入手順を調べてみると、FerrumはPDF生成するために書くコードが多いようです。
副校長室の共有パソコンは、韓国版JICAであるKOICAからもらったもので、性能も悪くなく、カード出力業務に関してもそこまで負荷がかかるものではないと思いましたので、実装がすぐにできそうなGroverを使ってみることにしました。
Grover を使ってみた感想
本当に簡単にPDF出力ができました。
実際にやったことを以下にまとめます。
まずはpuppeteerをインストール
npm install puppeteer
grover をGemfileに追加してbundle install
gem "grover"
config/initializers/grover.rb を修正
Grover.configure do |config|
config.options = {
format: 'A4',
margin: {
top: '5px',
bottom: '10cm'
},
viewport: {
width: 640,
height: 480
},
prefer_css_page_size: true,
emulate_media: 'screen',
cache: false,
timeout: 0, # Timeout in ms. A value of `0` means 'no timeout'
launch_args: ['--font-render-hinting=medium', '--lang=kh', '--allow-http-screen-capture'],
wait_until: 'networkidle0',
display_url: "http://localhost:3000",
}
end
controller の処理は以下のような感じ
def download_pdf
@students = Student.search_by_ids(params[:student_ids])
respond_to do |format|
format.pdf do
send_data(generate_pdf(), filename: 'students_id_card.pdf', type: 'application/pdf')
end
end
def generate_pdf
html_content = render_to_string(
template: 'pdf_templates/_id_card',
formats: [:html],
layout: "pdf"
)
Grover.new(html_content, print_background: true).to_pdf
end
ね、簡単でしょ?
チョムリアップリア
いかがでしたでしょうか。
IDカード作り、印刷して長さを測ったり、フォントがあぁだとかクメール語の間違い探しを副所長たちとわいわいがやがややったりして、なかなか楽しかったです。
次回は最終回です!お楽しみに!