前回までで Profile 情報を編集する基本ができたので、次に Profile 情報にアバターを追加していきます。
Rails 5.2.3 には、ActiveStorage があって、そちらでファイルのアップロードに対応可能ですが、今回は使いなれば CarrierWave を使って実装していきます。
CarrierWave の設定
CarrierWave gem のインストール
すでに Gemfile に CarrierWaev を指定してインストール済みの前提です。もしインストールしていない場合は、Gemfile に mini_magick と carrierwave を記載して install しておいてください。
1 2 |
gem 'mini_magick' gem 'carrierwave' |
1 |
$ bundle install |
アバター用 CarrierWave の設定
Profile の avatar 用のアップローダを作成します。
1 2 |
$ bundle exec rails g uploader profile_avatar create app/uploaders/profile_avatar_uploader.rb |
Profile モデルとの紐付けを実施
1 2 3 4 5 |
class Profile < ApplicationRecord belongs_to :user mount_uploader :avatar, ProfileAvatarUploader end |
app/uploaders/profile_avatar_uploader.rb で、このアップローダに対する設定を行う
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
class ProfileAvatarUploader < CarrierWave::Uploader::Base # いまは使っていないが、アップロード時に画像サイズ変更等行う場合 # mini_magick を使用 include CarrierWave::MiniMagick storage :file def store_dir "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}" end # アップロードされたファイルがない場合に表示するデフォルトの画像の指定 # app/assets/images/fallback/default_user_avatar.png にファイルを置く def default_url(*args) ActionController::Base.helpers.asset_path("fallback/default_user_avatar.png") end # アップロード可能なファイル拡張子を jpg, jpeg, png, gif に制限 def extension_whitelist %w(jpg jpeg png gif) end end |
アップロードファイルがない場合のデフォルト画像の設定
1 2 |
$ mkdir app/assets/images/fallback $ cp {デフォルトのアバターに使いたいpngファイル} app/aseets/images/fallback/default_user_avatar.png |
CarrierWave の動作確認
コマンドラインで動作を確認します。現状、ファイルをアップロードしていないので、デフォルトのファイルパスが返ってきています。
1 2 3 4 5 6 7 8 |
$ bundle exec rails c Loading development environment (Rails 5.2.3) irb(main):001:0> user = User.first User Load (0.2ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ? [["LIMIT", 1]] => #<User id: 1, email: "kayama.hiroshi@example.com", created_at: "2019-09-17 03:30:14", updated_at: "2019-09-17 03:30:14", username: "kayama.hiroshi"> irb(main):002:0> user.profile.avatar.to_s Profile Load (0.1ms) SELECT "profiles".* FROM "profiles" WHERE "profiles"."user_id" = ? LIMIT ? [["user_id", 1], ["LIMIT", 1]] => "/assets/fallback/default_user_avatar-42ad2b50437189d43e6ac94ade8e089a6c029504fa888b9f587796108639c529.png" |
アカウントの View の変更
ここまででデフォルトの画像の表示が可能となったので、アカウントの表示画面でアバターを表示するように変更します。
app/views/accounts/show.html.erb の <div class=”col-sm-4″> </div> で囲まれた部分にアバター表示を追記します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<div class="card col-sm-10 mx-auto mt-5 px-0"> <div class="card-header bg-white"> <h2>アカウント情報</h2> </div> <div class="card-body"> <div class="row"> <div class="col-sm-8"> <!-- 略 --> </div> <div class="col-sm-4"> <!-- アバターファイルの表示 --> <div class="d-flex flex-column"> <%= image_tag current_user.profile.avatar.to_s, :class => "float-center border mb-2 mx-auto" %> 編集 </div> </div> </div> </div> </div> |
こんな画面が見えるようになる(はず
アバターアップロード機能の追加
Profile.name と同様に DHH 流ルーティングでアバターアップロード機能を実装します。
コントローラの作成
Profile.name と同様に、コントローラを作成します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
$ bundle exec rails g controller accounts/avatars edit update create app/controllers/accounts/avatars_controller.rb route namespace :accounts do get 'avatars/edit' get 'avatars/update' end invoke erb create app/views/accounts/avatars create app/views/accounts/avatars/edit.html.erb create app/views/accounts/avatars/update.html.erb invoke test_unit create test/controllers/accounts/avatars_controller_test.rb invoke helper create app/helpers/accounts/avatars_helper.rb invoke test_unit invoke assets invoke coffee create app/assets/javascripts/accounts/avatars.coffee invoke scss create app/assets/stylesheets/accounts/avatars.scss |
以下のように編集します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
class Accounts::AvatarsController < ApplicationController before_action :authenticate_user! before_action :set_profile def show end def update respond_to do |format| if @profile.update(profile_params) format.html { redirect_to account_path, notice: "Profile was successfully updated." } else format.html { render :edit } end end end private def set_profile @profile = current_user.profile end def profile_params params.require(:profile).permit(:avatar, :avatar_cache, :remove_avatar) end end |
ルーティング設定
Profile.name と同様にルーティングを設定します。すでにルーティングは設定されていますが、これを削除して定義します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
Rails.application.routes.draw do resource :account, :only => [:show] do resource :name, :only => [:edit, :update], module: "accounts" resource :avatar, :only => [:edit, :update], module: "accounts" end # devise_for :users devise_for :users, controllers: { sessions: 'users/sessions', passwords: 'users/passwords', registrations: 'users/registrations' } get 'home/index' root to: "home#index" # For details on the DSL available within this file, # see http://guides.rubyonrails.org/routing.html end |
アバターアップロード用の View を作成
CarrierWave の例によくあるように View を作成します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
<div class="card col-sm-10 mt-5 mx-auto px-0"> <div class="card-header bg-white"> <H3>プロフィール写真を変更する</h3> </div> <div class="card-body"> <%= form_with(model: @profile, url: account_avatar_path, method: :put, local: true) do |form| %> <div class="form-group row"> <div class="col-sm-4"> <div class="account-profile-img mb-3"> <%= image_tag @profile.avatar.to_s, :id => "avatar-prev" %> </div> <% if @profile.avatar? %> <label><%= form.check_box :remove_avatar %> 画像を削除する</label> <% else %> <%= form.hidden_field :avatar_cache %> <% end %> </div> <div class="col-sm-8"> <%= form.file_field :avatar, :id => "avatar-img", :class => "form-control-file" %> </div> </div> <div class="actions float-right"> <%= link_to 'キャンセル' , account_path, :class => "btn btn-light" %> <%= form.submit "画像を更新", :class => "btn btn-primary" %> </div> </div> <% end %> </div> |
accounts/avatars/edit を叩くと、このような画面が出てくると思います。そしてファイル選択してアップロードすればアカウント表示画面に戻ってアバターが切り替わっているはずです。
アカウント表示 View からアバターアップロードへのリンク作成
アカウント表示 View のアバターの下の「編集」に、作成したアバターアップロードへのリンクを付与します。
1 2 3 4 5 6 7 |
<div class="col-sm-4"> <!-- アバターファイルの表示 --> <div class="d-flex flex-column"> <%= image_tag current_user.profile.avatar.to_s, :class => "float-center border mb-2 mx-auto" %> <%= link_to "編集", edit_account_avatar_path %> </div> </div> |
スタイル等の指定
あとは、ファイルアップロード前に確認可能な Javascript を適用したり、アバターを表示する際に画像のサイズを指定して centering して表示する CSS の設定を行ってください。