この記事では、Rails 5.2からの標準機能であるActiveStorageを使って画像アップロード機能を実装するポイントを紹介します。
1. バージョン情報
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]) %>
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' %>
【参考】