0. はじめに
Railsで画像アップロードといえばCarrierWave
とMiniMagick
が鉄板ですね。
数年前、プログラミングスクールに通っていた際にはあまり理解していなかった画像アップロード機能。
超久々に触ったので備忘録として残します🙏
ActiveStorage
という選択肢もありますが、あまり優位性がなさそうだったので採用を見送りました。
参考: ActiveStorage vs CarrierWave
1. 作業環境
OS: macOS Big Sur 11.5.1
Ruby: 3.0.2
Rails: 6.1.4
2. 環境構築
2-1. Gemのインストール
CarrierWave
とMiniMagick
をGemfileに追加してbundle install
します。
gem 'carrierwave', '~> 2.0'
gem 'mini_magick'
% bundle install
2-2. Uploaderクラスの作成
Gemがインストールできたら、次はUploader
を作成しましょう。
CarrierWave
のUploader
は、画像の保存場所や保存ファイル名、併用するライブラリ等を設定するためのクラスです。
Uploader
は下記コマンドで自動生成されます。
ちなみにimage
の部分は任意の文字列で問題ありません。
画像を扱うということが分かりやすいように、今回はimage
としてます。
% bundle exec rails g uploader image
するとapp/uploaders/image_uploader.rb
というファイルが生成されます。
中身はこんな感じ。あとで各種設定をイジるので一旦このまま次に進みましょう。
class ImageUploader < CarrierWave::Uploader::Base
# Include RMagick or MiniMagick support:
# include CarrierWave::RMagick
# include CarrierWave::MiniMagick
# Choose what kind of storage to use for this uploader:
storage :file
# storage :fog
# Override the directory where uploaded files will be stored.
# This is a sensible default for uploaders that are meant to be mounted:
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
# Provide a default URL as a default if there hasn't been a file uploaded:
# def default_url(*args)
# # For Rails 3.1+ asset pipeline compatibility:
# # ActionController::Base.helpers.asset_path("fallback/" + [version_name, "default.png"].compact.join('_'))
#
# "/images/fallback/" + [version_name, "default.png"].compact.join('_')
# end
# Process files as they are uploaded:
# process scale: [200, 300]
#
# def scale(width, height)
# # do something
# end
# Create different versions of your uploaded files:
# version :thumb do
# process resize_to_fit: [50, 50]
# end
# Add an allowlist of extensions which are allowed to be uploaded.
# For images you might use something like this:
# def extension_allowlist
# %w(jpg jpeg gif png)
# end
# Override the filename of the uploaded files:
# Avoid using model.id or version_name here, see uploader/store.rb for details.
# def filename
# "something.jpg" if original_filename
# end
end
2-3. 画像カラムにUploaderをマウント
Uploader
は画像保存に関する設定ファイルです。
このままでは役に立ちません。
画像を保存するためのカラムにマウントする必要があります。
例えばusersテーブル
に画像を保存するためのphotoカラム
があったとします。
その場合はUserモデル
に下記の設定をします。
class User < ApplicationRecord
mount_uploader :photo, ImageUploader
end
2-4. MiniMagickの設定
次はMiniMagick
の設定をします。
MiniMagick
は、サイズやアスペクト比の変更などに必要な画像処理のためのライブラリです。
設定はとっても簡単。
app/uploaders/image_uploader.rb
の一部コメントアウトを解除しましょう。
class ImageUploader < CarrierWave::Uploader::Base
# Include RMagick or MiniMagick support:
# include CarrierWave::RMagick
include CarrierWave::MiniMagick # <- ここのコメントアウトを外しただけ
たったこれだけ。
これで最低限の画像アップロード機能は完成です🙆♂️
3. Uploaderの設定を変更する
次はUploader
の設定を変更していきます。
app/uploaders/image_uploader.rb
のコードを上から見ていきましょう。
3-1. 画像の保存場所
画像の保存場所はローカルストレージかクラウドストレージの2種類です。
実用的な使い方をするのであればクラウドストレージ以外に選択肢はありませんが、本題ではないので今回はローカルストレージにします。
設定場所はココ。
ローカルストレージの場合は:file
、クラウドストレージの場合は:fog
にします。
# Choose what kind of storage to use for this uploader:
storage :file
# storage :fog
ちなみにクラウドストレージを使用する場合は、これ以外にも設定やGemの追加が必要となります。
詳しくは公式ドキュメント参照
3-2. 保存ディレクトリ
画像を保存するディレクトリを定義します。
デフォルトではこのようになっています。
# Override the directory where uploaded files will be stored.
# This is a sensible default for uploaders that are meant to be mounted:
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
このままの設定で画像保存をすると、Railsアプリにuploads/user/photo/1
のようなディレクトリが自動生成され、その中に画像ファイルが保存されます。
特に問題ないので今回はこのままにして進みます。
3-3. 保存サイズとアスペクト比
MiniMagick
のおかげで様々なサイズやアスペクト比を設定することができます。
設定部分はこちら。
# Process files as they are uploaded:
# process scale: [200, 300]
一旦ここを下記のように変更します。
# Process files as they are uploaded:
process resize_to_fit: [200, 200]
この場合はアスペクト比を保ったまま横200px・縦200px
の大きさに収まるよう画像を保存してくれます。第一引数が横サイズ、第二引数が縦サイズの指定です。
他にも下記のような保存方法があります。
3-4. サムネサイズの設定
画像は表示箇所によってサイズを変えたい場合があります。
例えばヘッダーやユーザーの一覧画面でアイコンを表示する場合は、少し小さめなサイズで表示したいですよね?
そんな設定はココで出来ます。
# Create different versions of your uploaded files:
# version :thumb do
# process resize_to_fit: [50, 50]
# end
version
の後には好きな名称を指定できます。
そして保存方法は3-3. 保存サイズとアスペクト比
で説明したものがそのまま使えます。
分かりやすく設定例を挙げておきましょう。
# Create different versions of your uploaded files:
version :icon do
process resize_to_fit: [50, 50]
end
version :icon_large do
process resize_to_fit: [100, 100]
end
このように複数のversion
を定義することができるので必要な分だけ設定しておきましょう。
今回はヘッダーで使うアイコンは小さめに、ユーザー一覧画面で使うアイコンは少し大きめに表示したい場合を想定しています。
画像それぞれ以下のようなメソッドで表示することが可能です。
(※ログイン中ユーザーをcurrent_user
とした場合)
<!-- 通常の画像表示 -->
<%= image_tag current_user.photo_url %>
<!-- 小さめアイコンの表示 -->
<%= image_tag current_user.photo_url(:icon) %>
<!-- 大きめアイコンの画像表示 -->
<%= image_tag current_user.photo_url(:icon_large) %>
3-5. 許容する拡張子の設定
どんなファイルを受け入れるか設定することができます。
これにより悪意あるスクリプトファイルのアップロードを防ぐことができます。
# Add an allowlist of extensions which are allowed to be uploaded.
# For images you might use something like this:
# def extension_allowlist
# %w(jpg jpeg gif png)
# end
通常はコメントアウトを外すだけで十分だと思います。
# Add an allowlist of extensions which are allowed to be uploaded.
# For images you might use something like this:
def extension_allowlist
%w(jpg jpeg gif png)
end
3-6. 保存ファイル名
保存ファイル名を変更したい場合、あると思います。
該当箇所はこちらです。
# Override the filename of the uploaded files:
# Avoid using model.id or version_name here, see uploader/store.rb for details.
# def filename
# "something.jpg" if original_filename
# end
ファイル名をどのように変更するか、あまりいいイメージが湧かなかったので説明は割愛します😋 笑
最後に
以上で基本的な設定は終了です。
あとは使いながら自分の好きな設定に適宜変更してみてください👍
参考資料
CarrierWave
MiniMagick
CarrierWaveを使って、ユーザー画像を設定する。
CarrierWave+MiniMagickで使う、画像リサイズのメソッド