wicked_pdfを導入するまで2020

### 環境
* OS
    * 開発PC： macOS Mojave
    * サーバー： Amazon Linux
* ruby 2.6.1
* Rails 5.2.2

### 初期段階
ミニマムで実装すると以下のようになります。
また、`layout`で指定するファイルは`app/views/layouts`に配置する必要があります。

```:ディレクトリ構成
src
├── app
│   ├── assets
│   │   └── stylesheets
│   │       └── sample
│   │           └── sample.sass
│   ├── controller
│   │   └── sample
│   │       └── sample_controller.rb
│   └── views
│       ├── sample
│       │   ├── sample.html.slim
│       └── layouts
│           └── pdf_for_sample.html.slim
└── Gemfile 
```

```:sample_controller.rb
def generate_pdf
  respond_to do |format|
    format.html { redirect_to sample_generate_pdf_path(format: :pdf)}
    format.pdf do
      if params[:debug].present?
        render pdf: 'sample',
               title: 'sample.pdf',
               encoding: 'UTF-8',
               layout: 'pdf_for_sample.html.slim',
               template: "sample/sample.html.slim",
               show_as_html: params[:debug].present?
      else
        render pdf: 'sample',
               title: 'sample.pdf',
               encoding: 'UTF-8',
               layout: 'pdf_for_sample.html.slim',
               template: "sample/sample.html.slim",
               show_as_html: params[:debug].present?
      end
    end
  end
end
```
```:pdf_for_sample.html.slim
 doctype html 
 html[lang="ja" xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" dir="ltr"]
   head 
     / メインのcss 
     = wicked_pdf_stylesheet_link_tag 'sample/sample', media: 'all'
   body 
     .sample
       .sample-text コンテンツ
```
```:sample.html.slim
# 空っぽ
```
```:Gemfile
gem 'wicked_pdf'
gem 'wkhtmltopdf-binary'
```

### layoutとtemplateを使い分ける
最初は違いがわかりにくかったのですが、`layout`のファイルは共通、`template`は個別のHTMLを描写するものとし、`layout`から`template`を呼び出す作りにするのが良さそうです。

```:pdf_for_sample.html.slim
 doctype html 
 html[lang="ja" xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" dir="ltr"]
   head 
     / メインのcss 
     = wicked_pdf_stylesheet_link_tag 'sample/sample', media: 'all'
   body 
     = yield
```
```:sample.html.slim
.sample
  .sample-text コンテンツ
```

### A4横向き＆pdfファイル全体に背景画像を使いたい
筆者の場合A4かつ横向きで生成する必要があったので、`page_size`と`orientation`を指定します。
（page_sizeはデフォルトでA4なので指定は不要ですが、可読性のため明示的に指定しました）

```:sample_controller.rb
def generate_pdf
  respond_to do |format|
    format.html { redirect_to sample_generate_pdf_path(format: :pdf)}
    format.pdf do
      if params[:debug].present?
        render pdf: 'sample',
               title: 'sample.pdf',
               encoding: 'UTF-8',
               orientation: 'Landscape',  #横向き
               page_size: 'A4',
               margin: { top: 0,
                         bottom: 0,
                         left: 0,
                         right: 0 },
               layout: 'pdf_for_sample.html.slim',
               template: "sample/sample.html.slim",
               show_as_html: params[:debug].present?
      else
        render pdf: 'sample',
               title: 'sample.pdf',
               encoding: 'UTF-8',
               orientation: 'Landscape',  #横向き
               page_size: 'A4',
               margin: { top: 0,
                         bottom: 0,
                         left: 0,
                         right: 0 },
               layout: 'pdf_for_sample.html.slim',
               template: "sample/sample.html.slim",
               show_as_html: params[:debug].present?
      end
    end
  end
end
```


次にpdf全体を覆う背景画像を当て込みます。
デフォルトでmarginが設定されているので初期化し、かつA4に合うよう調整した結果、heightを`991px`に設定しました。

```:sample.sass
.sample
  background: sample.png
  background-size: cover
  height: 991px
```

### 画面遷移を行わず、PDFのファイルダウンロードまで行いたい
筆者のPJでは生成したpdfファイルはユーザーのPCにダウンロードされる想定でしたが、このままだと、「ボタンクリックなどでPDF生成実行→pdfファイル画面へ遷移→ダウンロードボタンをクリック→ファイルがダウンロードされる」と言うフローになり、やや煩雑です。
上記を「ボタンクリックなどでPDF生成実行→ファイルがダウンロードされる」と言うフローにするため、以下の記述に変更します。

```:sample_controller.rb
def generate_pdf
  respond_to do |format|
    format.html { redirect_to sample_generate_pdf_path(format: :pdf) }
    format.pdf do
      if params[:debug].present?
        render pdf: 'sample',
               title: 'sample.pdf',
               encoding: 'UTF-8',
               orientation: 'Landscape',
               page_size: 'A4',
               margin: { top: 0,
                         bottom: 0,
                         left: 0,
                         right: 0 },
               layout: 'pdf_for_sample.html.slim',
               template: "sample/sample.html.slim",
               show_as_html: params[:debug].present?
      else
        pdf = render_to_string pdf: 'sample',
                               title: 'sample.pdf',
                               encoding: 'UTF-8',
                               orientation: 'Landscape',
                               page_size: 'A4',
                               margin: { top: 0,
                                         bottom: 0,
                                         left: 0,
                                         right: 0 },
                               layout: 'pdf_for_sample.html.slim',
                               template: "sample/sample.html.slim",
                               show_as_html: params[:debug].present?
        send_data pdf, filename: "sample.pdf"
      end
    end
  end
end
```

`filename: "sample.pdf"`でダウンロードされる際のファイル名が指定可能です。

### Amazon LinuxでRuntime errorになる
環境依存問題その1
ローカルで動作確認をしていざデプロイ！と思ったらPDF生成実行で500エラー（`Runtime error`）となり動かない...
どうやら、AmazonLinuxは動作環境外のようでした。
調べてみるとAmazonLinux対応版のブランチがあるようなので、指定したら正常に動作しました。

```:Gemfile
gem 'wicked_pdf'
gem 'wkhtmltopdf-binary',
  git: 'https://github.com/entretechno/wkhtmltopdf_binary_gem',
  branch: 'amazon-linux'
```

### 日本語が文字化けする
環境依存問題その2
PDF生成の際にはクライアントではなくサーバー側のフォントを参照するらしく、日本語が文字化けしてまともに動かない状態に。
そのためサーバーに日本語フォントをインストールした上で、cssからスタイルに適用します。
今回はyumで手軽にインストール可能なIPAフォントを利用しました。
（本当はnotoなどのgoogleフォントが使えれば尚良かったのですが、筆者の環境では正常に読み込めませんでした）

```
sudo yum -y install ipa-gothic-fonts ipa-mincho-fonts
```
```:sample.sass
.sample
  background: sample.png
  background-size: cover
  height: 991px
.sample-text
  font-family: 'IPAMincho', 'IPA明朝'
```

また、`serif`、`san-serif`は、フォントをインストールしない状態でも描画可能だったので、試してみるといいかもしれません。

### 最終形
上記をまとめると以下になります。

```:sample_controller.rb
def generate_pdf
  respond_to do |format|
    format.html { redirect_to sample_generate_pdf_path(format: :pdf) }
    format.pdf do
      if params[:debug].present?
        render pdf: 'sample',
               title: 'sample.pdf',
               encoding: 'UTF-8',
               orientation: 'Landscape',
               page_size: 'A4',
               margin: { top: 0,
                         bottom: 0,
                         left: 0,
                         right: 0 },
               layout: 'pdf_for_sample.html.slim',
               template: "sample/sample.html.slim",
               show_as_html: params[:debug].present?
      else
        pdf = render_to_string pdf: 'sample',
                               title: 'sample.pdf',
                               encoding: 'UTF-8',
                               orientation: 'Landscape',
                               page_size: 'A4',
                               margin: { top: 0,
                                         bottom: 0,
                                         left: 0,
                                         right: 0 },
                               layout: 'pdf_for_sample.html.slim',
                               template: "sample/sample.html.slim",
                               show_as_html: params[:debug].present?
        send_data pdf, filename: "sample.pdf"
      end
    end
  end
end
```
```:pdf_for_sample.html.slim
 doctype html 
 html[lang="ja" xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" dir="ltr"]
   head 
     / メインのcss 
     = wicked_pdf_stylesheet_link_tag 'sample/sample', media: 'all'
   body 
     = yield
```
```:sample.html.slim
.sample
  .sample-text コンテンツ
```
```:sample.sass
.sample
  background: sample.png
  background-size: cover
  height: 991px
.sample-text
  font-family: 'IPAMincho', 'IPA明朝'
```
```:Gemfile
gem 'wicked_pdf'
gem 'wkhtmltopdf-binary',
  git: 'https://github.com/entretechno/wkhtmltopdf_binary_gem',
  branch: 'amazon-linux'
```