はじめに
deviseで導入したユーザー認証機能にユーザーのプロフィール画像を追加したかったので、はじめはcarrierwaveなどを使って画像をアップロードしようと考えていたがRails 5.2から導入されたActive Storageを使えば、Usersテーブルに画像用のカラムを追加することなくプロフィール画像を設定できるようなので使ってみました。
deviseは導入済みという前提で進めていきます。
環境
ruby 2.6.5
rails 5.2.3
Active Storageを準備する
$ rails active_strage:install
$ rails db:migrate
このコマンドの実行で2つのテーブルが作成されます。
- active_storage_blobs
- active_storage_attachments
active_storage_blobs
ファイル名やファイルの種類、バイト数とかを保持するテーブルみたいです。
active_storage_attachments
このテーブルは、active_storage_blobsとActive Recordを紐付ける中間テーブルとしての役割があるようです。
Userモデル
deviseで生成されたUserモデルにhas_one_attached :avatar
を追加します。
これは1つの画像ファイルを添付するためのもので、複数ファイルを添付したい場合はhas_many_attached :images
とします。
class User < ApplicationRecord
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
# :avatarの部分は用途に合わせて :image :photoでも可
has_one_attached :avatar
end
コントローラーにストロングパラメータを設定する
ユーザー編集画面でプロフィール画像をアップロードしたいので、編集画面で画像ファイルを受け取れるようにストロングパラメータを設定します
class ApplicationController < ActionController::Base
# deviseコントローラにストロングパラメータを追加
before_action :configure_permitted_parameters, if: :devise_controller?
protected
# 編集画面から画像を受け取れるよう設定
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:account_update, keys: %i(avatar))
end
end
ストロングパラメータの詳しい設定は以下で確認できます。
ビューに追加
プロフィール画像のアップロード用と表示用のヘルパーをビューファイルに追加します。
ユーザー編集画面
.
.
.
<div class="field">
<%= f.label :current_password %> <i>(we need your current password to confirm your changes)</i><br />
<%= f.password_field :current_password, autocomplete: "current-password" %>
</div>
<%# 追加 %>
<%= f.file_field :avatar %>
<div class="actions">
<%= f.submit "Update" %>
</div>
.
.
.
ユーザー詳細画面
<p><%= @user.email %></p>
<% if @user.image.attached? %>
<%= image_tag @user.avatar %>
<% end %>
<%= link_to "編集", edit_user_registration_path %>
ユーザー詳細画面は初期状態のdeviseには無いので追加する必要があります。
下の記事が分かりやすく参考になりました。
Active Storageを使うと簡単だった
以上でプロフィール画像のアップロードから表示までが完了しました。
Active Storageを使うとテーブルにカラムを追加する必要がないにも関わらず、usersテーブルにavatar
というカラムがあるかのように操作できるところが便利でした。
他にもActive Storageを使うことでAmazon S3やGoogle Cloud Strageなどへのアップロードが可能になるようです。