LoginSignup
24
23

More than 1 year has passed since last update.

Rails5でPrawnによるPDFを作成する

Last updated at Posted at 2018-09-06

はじめに

Rails5でPDFの作成をするのに便利なgemのPrawnの使用方法について、備忘録的にまとめておきます。どなたかの役に立てば幸いです。

環境

Rails 5.1.6

データベースはmysqlを使用

gemの導入

まずはprawn導入用のgemをGemfileに追記します。

Gemfile
gem 'prawn'
gem 'prawn-table'

bundle installします。

terminal
$ bundle install

ローカルサーバー等は再起動してください。

PDF用のクラスを作成

PDFの内容を作成するための専用クラスを作成します。
Prawnではcontrollerに直接PDFの内容を流し込んでもいいのですが、可読性・保守性ともに下がるため、専用のクラスを作成することがおすすめです。

terminal
$ mkdir app/pdfs
$ touch app/pdfs/record_pdf.rb # record_pdf.rbというファイル名で作成、model名はRecordPdfとなる

PDF作成用のモデルを作成します。
Prawn::Documentを継承するようにします。

app/pdf/record_pdf.rb
class RecordPdf < Prawn::Document

# recordにモデルなどのデータを渡します
def initialize(record)

  # superで初期設定を指定します(ページサイズ、マージン等)
  super(
    page_size: 'A4',
    top_margin: 40,
    bottom_margin: 30,
    left_margin: 20,
    right_margin: 20
  )

  @record = record # インスタンスを受け取り。コンポーネント作成時などにレコード内のデータを使える

end

end

フォントを指定

Prownはデフォルトでは日本語に対応していないので、日本語用のフォントを用意します。
日本語のフォントはここからダウンロードできます。

ダウンロードしたフォントはassets/fontsに入れます。
(ちなみにここ以外から入手したフォントでも動作できます。著作権に注意してください。)

app/pdf/record_pdf.rb
class RecordPdf < Prawn::Document

  def initialize(record)

    super(
      page_size: 'A4',
      top_margin: 40,
      bottom_margin: 30,
      left_margin: 20,
      right_margin: 20
    )

    font 'app/assets/fonts/ipaexg.ttf' # fontをパスで指定

    @record = record

  end

end

controllerの作成

controllerを作成します。すでに作成済みのコントローラを介して使用することもできます。

terminal
$ rails g controller record_pdfs index # コントローラ作成時にindexページも作成
app/controllers/record_pdfs_controller.rb
class RecordPdfsController < ApplicationController

  def index
    @records = Record.all # pdf上で使用するレコードのインスタンスを作成
    respond_to do |format|
      format.html
      format.pdf do

        # pdfを新規作成。インスタンスを渡す。
        pdf = RecordPdf.new(@records)

        send_data pdf.render,
          filename:    "sample.pdf",
          type:        "application/pdf",
          disposition: "inline" # 画面に表示。外すとダウンロードされる。
      end
    end
  end

end

PDFの表示

ページへのリンクはルーティングに依存するので、適宜確認して行ってください。
リンクの作成例は以下のようになります。

<%= link_to "PDFを表示", 適宜指定_path(format: "pdf") %>

モデルを編集します。

app/pdf/record_pdf.rb
class RecordPdf < Prawn::Document

  def initialize(record)

    super(
      page_size: 'A4',
      top_margin: 40,
      bottom_margin: 30,
      left_margin: 20,
      right_margin: 20
    )

    font 'app/assets/fonts/ipaexg.ttf'

    @record = record

    # きちんと日本語も表示されるか確認
    text 'hello こんにちは 春夏秋冬'

  end

end

このように表示されればOK
スクリーンショット 2018-09-06 17.30.58.png

カスタマイズ

Prawnは座標指定でテキスト等の表示位置を決められるため、グリッドを表示させておくと編集が楽。

app/pdf/record_pdf.rb
class RecordPdf < Prawn::Document

  def initialize(record)

    super(
      page_size: 'A4',
      top_margin: 40,
      bottom_margin: 30,
      left_margin: 20,
      right_margin: 20
    )

    @record = record

    font 'app/assets/fonts/ipaexg.ttf'

    stroke_axis # これでメモリが表示される

    text 'hello こんにちは 春夏秋冬'

  end

end

基準となるメモリが表示される

スクリーンショット 2018-09-06 17.32.41.png

PDF内のコンポーネント作成

app/pdf/record_pdf.rb
class RecordPdf < Prawn::Document

  def initialize(record)

    super(
      page_size: 'A4',
      top_margin: 40,
      bottom_margin: 30,
      left_margin: 20,
      right_margin: 20
    )

    @record = record

    font 'app/assets/fonts/ipaexg.ttf'

    stroke_axis

    # 下記で作成したコンポーネントを表示順に
    header
    move_down 50
    contents

  end

  # コンポーネント作成
  def header
    text 'PDFのタイトル', size: 50
    move_down 20
    text '作成者氏名', size: 14
  end

  def contents
    text '本文'
    move_down 10
    text 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. 
          Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. 
          Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. 
          Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.'
  end

end

表示確認

スクリーンショット 2018-09-06 17.47.03.png

インスタンスの利用

コントローラで渡して入れば、データベースから取得したデータをPDF内で利用可能

app/controllers/record_pdfs_controller.rb
class RecordPdfsController < ApplicationController

  def index
    @records = Record.all # pdf上で使用するレコードのインスタンスを作成
    respond_to do |format|
      format.html
      format.pdf do

        pdf = RecordPdf.new(@records) # ここで受け取っている

        send_data pdf.render,
          filename:    "sample.pdf",
          type:        "application/pdf",
          disposition: "inline" # 画面に表示。外すとダウンロードされる。
      end
    end
  end

end
app/pdf/record_pdf.rb
class RecordPdf < Prawn::Document

  def initialize(record) # 受け取ったものがrecordに入っている

    super(
      page_size: 'A4',
      top_margin: 40,
      bottom_margin: 30,
      left_margin: 20,
      right_margin: 20
    )

    @record = record # メソッドで利用できるようにインスタンス化

    font 'app/assets/fonts/ipaexg.ttf'

    stroke_axis

    # 下記で作成したコンポーネントを表示順に
    header
    move_down 50
    contents

  end

  # コンポーネント作成
  def header
    text 'PDFのタイトル', size: 50
    move_down 20
    text '作成者氏名', size: 14
  end

  def contents
    text '本文'
    move_down 10
    text 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. 
          Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. 
          Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. 
          Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.'

    move_down 50

    text "データの内容は#{@record.data}です" # 例えば、このように利用できる

  end

end

以上です。

参考

24
23
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
24
23