初めて知ったShrineって何?
勉強を始めたばかりの私が、もくもく会に初めて参加させていただきました!
諸先輩方がお話ししていて耳にした「Shrine」という言葉。
調べてみると、Railsでファイルを扱うことのできるライブラリであることを知りました。
自分なりに調べたので、記事にして残します。
Shrine(シュライン)は
Shrineは、Rails標準の「Active Storage」とは異なり、 軽くて速くて自由度が高い、**ファイルアップロード用ライブラリと知りました。
画像・音声・PDF・動画など、さまざまなファイルを扱うことができ、 Active Storageの代わりとして使うことも可能らしいです。
Shrineでできること
| 機能 | 説明 |
|---|---|
| プラグイン構造 | 必要な機能だけを読み込むモジュール設計。軽くて拡張しやすい |
| クラウド保存OK | AWS S3・Google Cloud・Cloudinaryなどに簡単保存 |
| メモリに優しい | ストリーミング処理で大きなファイルも安定動作 |
| Rails以外でも使える | Ruby全般で利用可能 |
| 画像加工対応 | MiniMagick や libvips でリサイズ・サムネイル生成 |
| 直接アップロード | JavaScriptでS3へ直接アップロード可能 |
| バックグラウンド処理 | Sidekiqなどで非同期アップロード・削除 |
| テストが簡単 | メモリ上ストレージで高速テストが可能 |
Shrineの流れ(ざっくり)
[フォーム] → [コントローラ] → [Shrineアップローダー] → [ストレージ]
↑
[モデルに include]
ファイルをアップロードすると
- Shrine が「一時保存 → 本保存」を行う
- モデルに
image_data(JSON形式)として情報を保存 - 表示時に
image_urlでURLを取得
使い方
①Gemを追加する
# Gemfile
gem "shrine", "~> 3.0"
②初期設定する(config/initializers/shrine.rb)
require "shrine"
require "shrine/storage/file_system"
Shrine.storages = {
cache: Shrine::Storage::FileSystem.new("public", prefix: "uploads/cache"), # 一時保存
store: Shrine::Storage::FileSystem.new("public", prefix: "uploads") # 永続保存
}
Shrine.plugin :activerecord
Shrine.plugin :cached_attachment_data
Shrine.plugin :restore_cached_data
ActiveRecord対応、フォーム再表示時の保持が有効になるようです。
③DBにカラムを追加
rails generate migration add_image_data_to_photos image_data:text
image_data カラムにはファイルのメタ情報がJSON形式で保存されるようです。
④アップローダーを作る
# app/uploaders/image_uploader.rb
class ImageUploader < Shrine
# ここに画像加工や検証などを追加できる
end
⑤モデルに組み込む
class Photo < ApplicationRecord
include ImageUploader::Attachment(:image)
end
これで photo.image や photo.image_url が使えるようになるようです。
⑥フォームを作る
<%= form_for @photo do |f| %>
<%= f.hidden_field :image, value: @photo.cached_image_data, id: nil %>
<%= f.file_field :image %>
<%= f.submit "アップロード" %>
<% end %>
⑦コントローラ
def create
Photo.create(photo_params)
end
private
def photo_params
params.require(:photo).permit(:image)
end
⑧表示
<%= image_tag @photo.image_url %>
S3に保存する場合
require "shrine/storage/s3"
s3_options = {
bucket: "my-bucket",
region: "ap-northeast-1",
access_key_id: "XXX",
secret_access_key: "YYY",
}
Shrine.storages = {
cache: Shrine::Storage::S3.new(prefix: "cache", **s3_options),
store: Shrine::Storage::S3.new(**s3_options)
}
これでアップロードしたファイルが自動的にS3に保存されるようです。
Shrineの中身をざっくり理解
| レイヤー | 役割 | 例 |
|---|---|---|
| Shrineクラス | アップロードの基盤(プラグインを組み込む) | Shrine.plugin :activerecord |
| Uploader | Shrineを継承し、設定を書く | class ImageUploader < Shrine |
| Attachmentモジュール | モデルにincludeして利用 | include ImageUploader::Attachment(:image) |
| Attacherクラス | 実際のアップロードや削除を担当 | photo.image_attacher |
| UploadedFile | 保存されたファイルを表すオブジェクト |
photo.image や .url
|
Shrineでできる応用例
MiniMagickで画像サイズを自動変換
Shrine.plugin :derivatives, create_on_promote: true
require "image_processing/mini_magick"
class ImageUploader < Shrine
Attacher.derivatives do |original|
magick = ImageProcessing::MiniMagick.source(original)
{
small: magick.resize_to_limit!(300, 300),
medium: magick.resize_to_limit!(600, 600)
}
end
end
非同期アップロード(Sidekiq)
Shrine.plugin :backgrounding
Shrine::Attacher.promote_block do
PromoteJob.perform_async(self.class.name, record.class.name, record.id, name, file_data)
end
ブラウザから直接S3アップロード
Shrine.plugin :upload_endpoint
mount Shrine.upload_endpoint(:cache) => "/upload"
まとめ
Shrineは...
- 大きなファイルも軽快に扱える
- S3やSidekiqとも連携ができる
- 画像・音声・PDFなどを扱うことができる
初学者の学び
今回は初めて「Shrine」というライブラリを知りました。
使ったことはありませんが、Active Storageの代わりに自由度の高いファイル管理ができるという点にとても興味を持ちました。
今後、自分のRailsアプリで画像や音声を扱う機能を作るときに、ぜひ一度Shrineを触ってみたいと思います。
記載内容が間違えていたら、すいません。