PDF出力してみたいんじゃ！ 【Thinreports + Rails】

どうも。とある六本木一丁目にある会社のエンジニアです。
というわけで [SmartHR Advent Calendar 2020](https://qiita.com/advent-calendar/2020/smarthr) の5日目だぜ。

## 目的
弊社プロダクトのPDF出力に [Thinreports](http://www.thinreports.org/) を使用しているのでお友達になりたかった。

## 使うもの
Thinreports + Rails でやっていきます

## ゴール
タイトルと本文がある書類をPDFで出力できるようにする！
簡単！

## やっていこう
とりあえず rails new

```
rails new thinreports_demo --skip-test
```

gem 追加

```ruby
gem 'thinreports'
```

```
bundle install
```

### サンプルPDF出力する準備
ThinreportsでのPDF出力には `tlf` というフォーマットのデータが必要なので後々用意する必要があるので先にrails側の準備を整える

コントローラーを用意

```
rails g controller pdfs index sample_doc
```

sample_doc用にroutesを修正

```ruby:routes.rb
Rails.application.routes.draw do
  root 'pdfs#index'
  resources :pdfs, only: :index do
    get :sample_doc, on: :collection
  end
end
```

views を修正

```erb:views/pdfs/index.html.erb
<h1>PDFにしてくれる君</h1>
<p>
  <%= link_to 'サンプル書類がみたい', sample_doc_pdfs_path %>
</p>
```

リンクにアクセスするとPDFを見れるようにしていく

![SS 123.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/118385/a4527267-8a66-ca37-ff75-36f5ae99c551.png)


### Thinreports Editor で TLFファイル 作る
公式を見て Thinreports Editorのインストール（必要なら Generatorの方も）
[Thinreports インストールガイド（公式）](http://www.thinreports.org/documentation/ja/getting-started/installation.html)

何はともあれ `Thinreports Editor` を起動

![SS 125.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/118385/bcaf6e1d-fb1e-d682-d238-a8e8e9c122ec.png)


新規作成から新しくA4の書類を作ります

後々のことを考えて

- タイトル
- 本文
- 著者

の３つを `テキストブロックツール` を使って作り出します

![SS_126.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/118385/547c01c8-8522-5e56-3baa-7a4f3f627bef.png)


app/pdfs 以下に保存（ファイル名は任意で）

![SS 127.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/118385/a5dab1ba-6a4c-fcf7-18a0-5eaaf2d7df19.png)


### PDFとして出力する設定をしていく
pdfsコントローラーにPDFを出力するための設定をする
詳しくは[ここら辺のクイックスタート](http://www.thinreports.org/documentation/ja/getting-started/quickstart.html) を参考にする


```ruby:pdfs_controller.rb
class PdfsController < ApplicationController
:
:
  def sample_doc
    report = Thinreports::Report.new(layout: "#{Rails.root}/app/pdfs/sample_doc.tlf")

    report.start_new_page
    # さっき作った title に value つっこんでる
    report.page.item(:title).value('PDFやで')
    # title 以外はあとでやるのでここではスルーします

    file = report.generate
    send_data(
      file,
      filename: 'filename_sample.pdf',
      type: 'application/pdf',
      disposition: 'inline'
    )
  end
end
```

先ほどのリンクからアクセスすると PDF出てくる 

![SS 128.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/118385/be425a8f-9b84-b10f-6d05-d278aa089310.png)


やったね✌️

### 書類らしきものを作る

ここら辺は scaffold しましょう

- Doc
    - title
    - content
    - author

```
rails g scaffold doc title content:text author
```

```
rails db:migrate
```

### 新しく TLFファイル を複製
内容は `sample_doc.tlf` と同じでよいので もう一つ TLF作る（特に意味はないのでsample_doc.tlfを使い回しでいいと思います）

### 書類らしきものごとにPDF出力できるようにする
routes の修正

```ruby:routes.rb
Rails.application.routes.draw do
  :
  :
  resources :docs do
    get :show_pdf
  end
  :
  :
end
```

コントローラー

```ruby:docs_controller.rb
class DocsController < ApplicationController
  :
  :
  def show_pdf
    @doc = Doc.find(params[:doc_id])
    report = Thinreports::Report.new(layout: "#{Rails.root}/app/pdfs/doc.tlf")

    report.start_new_page
    # 以下で各カラムごとのデータを入れる
    report.page.item(:title).value(@doc.title)
    report.page.item(:content).value(@doc.content)
    report.page.item(:author).value(@doc.author)

    file = report.generate
    send_data(
      file,
      filename: "doc_#{@doc.id}.pdf",
      type: 'application/pdf',
      disposition: 'inline'
    )
  end
  :
  :
end
```

リンクも忘れず

```erb:views/docs/index.html.erb
<p id="notice"><%= notice %></p>

<h1>Docs</h1>

<table>
  :
  <tbody>
    <% @docs.each do |doc| %>
      <tr>
        :
        <td><%= link_to 'ShowPDF', doc_show_pdf_path(doc) %></td>
        # ☝️追加
        :
      </tr>
    <% end %>
  </tbody>
</table>

<br>

<%= link_to 'New Doc', new_doc_path %>
```

### データを入れる
[ダミーテキストジェネレータ](https://webtools.dounokouno.com/dummytext/) とかを使ってデータ入れる

http://localhost:3000/docs/new から適当に

http://localhost:3000/docs はこんな感じ
![SS 130.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/118385/41c87e64-47e0-f689-fd26-565909109189.png)


![SS 129.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/118385/8fefab35-b042-1791-7bd3-d92644366938.png)


完成！！（見た目は整える時間なかった！）
やったね✌️

## まとめ
お友達になれました :blush: