ファイルアップロードを行うGem 「Shrine」の紹介

こんにちは!kossyです!




さて、今回はファイルアップロードを行うGem 「Shrine」の使い方をブログに残してみたいと思います。



環境

Ruby 2.6.6
Rails 6.0.4
shrine 3.4.0



実装

公式のGettingStartedに倣って実装していきます。

Getting Started · Shrine



まずはGemfileの編集

# Gemfile

gem 'shrine'

でbundle install

$ bundle install

config/initializers/shrine.rbを作成します。

$ touch config/initializers/shrine.rb

作成したファイルを以下のように編集します。

# config/initializers/shrine.rb

require "shrine"
require "shrine/storage/file_system"
 
Shrine.storages = { 
  cache: Shrine::Storage::FileSystem.new("public", prefix: "uploads/cache"), # temporary 
  store: Shrine::Storage::FileSystem.new("public", prefix: "uploads"),       # permanent 
}
 
Shrine.plugin :sequel # or :activerecord 
Shrine.plugin :cached_attachment_data # for retaining the cached file across form redisplays 
Shrine.plugin :restore_cached_data # re-extract metadata when attaching a cached file 
Shrine.plugin :rack_file # for non-Rails apps 

次にモデル(今回はApplicationRecordを継承したEmployeeモデルが存在するとします)の添付ファイル属性に名前を付ける方法を決定し、_dataテキストまたはJSON列を追加するマイグレーションファイルを作成します。

$ rails g migration AddImageDataToEmployee image_data:text
class AddImageDataToEmployee < ActiveRecord::Migration[6.0]
  def change
    add_column :employees, :image_data, :text
  end
end
$ rails db:migrate

次に、ファイルアップローダークラスを作成します。このクラスはshrineを継承して作成します。

$ mkdir app/uploader

$ touch app/uploader/image_uploader.rb
# app/uploader/image_uploader.rb

class ImageUploader < Shrine
end

次に、Employeeモデルにファイルアップロードに関する仮想的な属性を定義します。

# app/models/employee.rb

class Employee < ApplicationRecord
  include ImageUploader::Attachment(:image)
end

これでshrineを介したimageの読み書きが可能になります。

画像のリサイズ

画像の加工はimagemagickを用いて実装していきます。

$ brew install imagemagick
# Gemfile

gem 'image_processing'
gem 'mini_magick'
$ bundle install

config/initializers/shrine.rbにオプションを追加します。

# config/initializers/shrine.rb

require "shrine"
require "shrine/storage/file_system"

Shrine.storages = {
  cache: Shrine::Storage::FileSystem.new("public", prefix: "uploads/cache"), # temporary
  store: Shrine::Storage::FileSystem.new("public", prefix: "uploads"),       # permanent
}

Shrine.plugin :activerecord
Shrine.plugin :cached_attachment_data # for retaining the cached file across form redisplays
Shrine.plugin :restore_cached_data # re-extract metadata when attaching a cached file
Shrine.plugin :rack_file # for non-Rails apps
Shrine.plugin :derivatives, create_on_promote: true # 追加

次に、先ほど作成したImageUploaderクラスを修正します。

require "image_processing/mini_magick"
 
class ImageUploader < Shrine
  Attacher.derivatives do |original|
    magick = ImageProcessing::MiniMagick.source(original)
 
    { 
      large:  magick.resize_to_limit!(800, 800),
      medium: magick.resize_to_limit!(500, 500),
      small:  magick.resize_to_limit!(300, 300),
    }
  end
end

まとめ

公式のGettingStartedがかなり丁寧なので、最低限の導入であればそれほどてこずることなくできそうです。