What do you do when you generate a PDF in Rails? A little research reveals gems such as wicked_pdf and prawn.
This time, I found out about the existence of a gem that generates PDFs and images from HTML using Puppeteer / Chromium called grover and tried it, so I will leave a note.
Install puppeteer
npm install puppeteer
Described in Gemfile
gem 'grover'
Add the following to config / initializers / grover.rb.
# frozen_string_literal: true
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=ja'], #For Japanese display--lang=add ja
    wait_until: 'domcontentloaded'
  }
end
Describe the following in controllers / api / sample_controller.rb. Don't forget to describe the routing.
# frozen_string_literal: true
module Api
  class SampleController < ApplicationController
    include ActionController::MimeResponds #Respond in API mode_Required to use to
    def show
      controller = ActionController::Base.new
      html = controller.render_to_string(template: 'api/hoges/show', layout: 'pdf')
      pdf = Grover.new(html).to_pdf
      respond_to do |format|
        format.html
        format.pdf do
          send_data(pdf, filename: 'your_filename.pdf', type: 'application/pdf')
        end
      end
    end
Create layout file for pdf generation
views/layouts/pdf.html.erb
<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8" />
    <style>
    </style>
  </head>
  <body>
    <%= yield %>
  </body>
</html>
api/sample/show.html.erb
<p>Invoice</p>
<style>
p { font-size: 20px; }
</style>
I was able to easily generate a pdf. The processing time is also a level that does not matter. If you include puppeteer, you don't need to set fonts, so it looks good.
Recommended Posts