この記事では、Rails 5.2からの標準機能であるActiveStorageを使って画像アップロード機能を実装するポイントを紹介します。
1. バージョン情報
- macOS:12.6
- Ruby:3.1.2
- Rails:6.1.6
- image_processing:1.12.2
- active_storage_validations:0.9.8
2. 実装時のポイント
2-1. Active Storageのセットアップ
以下を実行して、migrationファイルを作成します。
$ rails active_storage:install
db/migrate/XXXX_create_active_storage_tables.active_storage.rbが作成される
migrationを実行します。
$ rails db:migrate
2-2. 画像アップロードと表示
各userにアバター画像を添付したい場合は、以下のようにUserモデルを定義します。
class User < ApplicationRecord
has_one_attached :avatar
end
以下のように書くことでフォームからアバター画像をアップロードできます。
<div class="field">
<%= f.label :avatar %>
<%= f.file_field :avatar %>
</div>
- ストロングパラメータに
avatarの追加が必要
以下のように書くことでアバター画像を表示できます。
<%= image_tag user.avatar if user.avatar.attached? %>
avatar.attached?で特定のuserがアバター画像を持っているかどうかを調べられます。
2-3. 画像のリサイズ
画像のリサイズのためにimage_processing gemが必要です。
Gemfileのimage_processing gemのコメントを解除します。
# Use Active Storage variant
gem 'image_processing', '~> 1.2'
image_processing gemを使うために、macにimagemagickとvipsをインストールします。
$ brew install imagemagick vips
variantメソッドで、添付ファイルごとに特定のサイズ違いの画像を生成できます。
<%= image_tag user.avatar.variant(resize_to_fit: [50, 50]) %>
- ImageProcessing::MiniMagick - README
- [https://qiita.com/wann/items/c6d4c3f17b97bb33936f:title]
2-4. バリアントプロセッサの変更
Active StorageのデフォルトのバリアントプロセッサはMiniMagickですが、Vipsも指定可能です。
Vipsに切り替えるには、config/application.rbに以下の設定を追加します。
config.active_storage.variant_processor = :vips
- Active Storage の概要 - 9 画像を変形する - Railsガイド
- config.active_storage.variant_processor - Railsガイド
- variant.rb - Rails API
設定した値はコンソールからも確認できます。
$ rails c
irb(main):001:0> Rails.application.config.active_storage.variant_processor
=> :vips
2-5. N+1問題の解決
Active Storageでは、画像ファイルを親子モデルのアソシエーションとして関係付けるため、N+1問題を引き起こす可能性があります。
このN+1問題を解決するためにwith_attached_属性名スコープを使用します。
以下のように、app/controllers/users_controller.rbでwith_attached_avatarとすることでN+1問題を回避することができます。
class UsersController < ApplicationController
def index
@users = User.all.with_attached_avatar
end
# 省略
end
- ActiveStorage::Attachment
- N+1を解決する - Rails 5.2新機能を先行チェック! TechRacho
- Active StorageのN+1問題に対処する - シュッと開発日記
- activestorage/lib/active_storage/attached/model.rb
2-6. バリデーション
アップロード可能なファイルの種類を限定する方法を紹介します。
方法1. active_storage_validationsを使用する
active_storage_validations gemを使用します。
Gemfileに以下を追記して、bundle installを実行します。
gem 'active_storage_validations'
app/models/user.rbに以下を追記します。
class User < ApplicationRecord
has_one_attached :avatar
validates :avatar, content_type: ['image/png', 'image/jpeg', 'image/gif']
end
方法2. 独自のバリデーションヘルパーを実装する
app/models/user.rbに以下を追記します。
class User < ApplicationRecord
has_one_attached :avatar
validate :image_check
private
def image_check
return unless avatar.attached?
return if avatar.image?
errors.add(:avatar, 'のContent Typeが不正です')
end
end
フォーム側からファイルの種類に制限をかけるためにacceptを使用します。
<%= f.file_field :avatar, accept: 'image/png,image/gif,image/jpeg' %>
【参考】