【Rails】ActiveStorageでPDFサムネイルを生成する方法

はじめに

こんにちは、株式会社TOKOSのツキヤです!
本記事では、ActiveStorageを使ってPDFファイルの1ページ目のプレビューを画像として表示する方法を紹介します💪
自分がWEBで探しても”コレ!”という記事が無かったので、誰かのお役に立てれば幸いです!

ActiveStorageの概要

前提として、ActiveStorageについて簡単に説明します!

ActiveStorageは、Ruby on Railsのフレームワークで画像をはじめとしたファイルを取り扱う際に使用するgemです!
画像ファイルを扱う他のgemもありますが、今現在はデフォルトでRailsに組み込まれているのでほぼほぼ一強かと思っています😎

ツキヤ
ツキヤ

特に意識していなければ、Gemfileに記述すらされていないけどデフォルトで使えるね!

PDFのサムネイルとは?

次に、PDFのサムネイルについてもサクッと解説します!

PDFサムネイルは、PDFファイルの内容を簡単にプレビューするための小さな画像です。
これにより、ユーザーはPDFファイルを開かずとも、その内容の概要を視覚的に把握することができます。
ウェブアプリケーションにおいて、PDFサムネイルの表示は、ユーザー体験を大幅に向上させますね✨

ActiveStorageの設定と準備

早速方法について解説します!
まずは、前準備です。

前提

今回は$ rails g model Article title: string body: textで生成したモデルに対してPDFを紐付けるようにします。

また、紐付け済みのPDFファイルのプレビューを生成するだけの解説に留めます🙇‍♂️
(ファイルをアップロードする方法の解説について、実装内容は画像と特に変わらないので他の記事に譲ります)

本環境

前提として、本記事を執筆する上での開発環境を紹介します!
今回はOS側にもパッケージを導入する必要があるのでDockerを使用しています🙏
なので、一旦ベースとなるDockerfileを下記します。

FROM ruby:3.2.2

RUN apt-get update -qq && apt-get install -y libmariadb-dev build-essential

WORKDIR /app
COPY Gemfile Gemfile
COPY Gemfile.lock Gemfile.lock
RUN bundle install
COPY . .

COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
EXPOSE 3000

CMD ["rails", "server", "-b", "0.0.0.0", "-p", "3000"]

実装をする上で変更をするのは3行目になります。
Dockerが分からない方は、3行目で自分のパソコンにパッケージをインストールしているということだけおさえておいてくれればOKです!

RailsプロジェクトでのActiveStorageの設定方法

まずはActiveStorageをインストールします!
…と言ったのですが、先程も書いたように、特に意識せずともインストール自体は勝手に完了しているはずです✨
一応config/application.rbを確認してrequire "active_storage/engine"という記述があるかどうかだけ確認してください!

require_relative "boot"

require "rails"
# Pick the frameworks you want:
require "active_model/railtie"
require "active_job/railtie"
require "active_record/railtie"
require "active_storage/engine" # コレが書いてあればOK!
require "action_controller/railtie"
require "action_mailer/railtie"
# 以下略 ...

次に、コマンドラインで下の2行のコマンドを打てばActiveStorageの準備は完了です!

$ rails active_storage:install
$ rails db:migrate

最後に、Articleモデルに pdf という名前で1対1でファイルを紐付けられるようにします!

class Article < ApplicationRecord
  has_one_attached :pdf
  # 以下略
end

これで準備完了です!
@article.pdfでpdfの情報を呼び出すことができるようになります✨

PDFサムネイルの生成方法

必要なパッケージのインストール・準備

PDFサムネイルの生成には、追加のライブラリやツールが必要になります。
今回やりたいことは「PDFサムネイルの生成」なので、特定のファイルに対して処理を行うため、それ用のパッケージをOSに対してインストールします!

FROM ruby:3.2.2

# 後ろの3つを新規に追加
RUN apt-get update -qq && apt-get install -y libmariadb-dev build-essential libvips42 mupdf mupdf-tools
# 以下略


上記をOSにインストールした上で、gemを追加します!

# ...
gem "image_processing"
gem "ruby-vips"

これでRuby(Rails)から直接これらのツールを利用できるようになります✨

最後に、 config/application.rbに追記します!

module App
  class Application < Rails::Application
    # ...
    
    # 下記を追記
    config.active_storage.previewers << ActiveStorage::Previewer::MuPDFPreviewer
  end
end

これで下準備は完了です😋

サムネイル画像の生成方法

あとは、html.erb 側で表示するだけです!

<% if @article.pdf.representable? %>
  <%= image_tag @article.pdf.preview(resize_to_limit: [210, 297]) %>
<% else %>
  <span>プレビューは表示できません</span>
<% end %>

representable?メソッドを使用してPDFファイルがプレビュー可能かどうかを確認します!
そして、previewメソッドでサムネイルを生成します。例えば上記のように@article.pdf.preview(resize_to_limit: [210, 297])は、横210px × 縦297px のサイズにリサイズされたサムネイルを生成します!

URLのみの生成方法

サムネイルの画像自体ではなく、そのURLのみを生成することも可能です。
その際には、追加で各環境ごとの設定が必要になります。今回は開発環境のconfig/environments/development.rbの例を下記します!

# ~~ 中略 ~~
  # ActiveStorageの設定
  config.active_storage.service = :local
  default_url_options[:host] = "localhost"
  default_url_options[:port] = 3000
# ~~ 中略 ~~

この設定をしておかないとエラーが出るので注意です🙏

上記準備をしたら、url_forメソッドを使用してURLを生成します。例えば、url_for(@article.pdf.preview(resize_to_limit: [210, 297]))で生成されたサムネイルのURLを返します。このURLをimgタグに埋め込むことで、ユーザーにサムネイルを表示できます✨

おわりに

ActiveStorageを使用することで、RailsにPDFサムネイルを簡単にすることができました!
皆さんも機会があればぜひ参考にしてください✨

Railsのことを詳しく知りたい方は、この本に分かりやすく書かれているので是非参考にしてみて下さい🙏