プロフィール編集画面

実装内容

プロフィール詳細ページ(/profile)と編集ページ(/profile/edit)を作成する
プロフィール編集画面からアバター画像をアップロードできるようにし、プロフィール詳細画面、ヘッダーアイコン、コメントしたユーザーのアイコン画像が表示されるようにする。

画像のカラムを作成
usersテーブルにavatarカラムを追加

$ rails g migration add_avatar_to_users avatar:string
$ rails db:migrate
== 20210623060835 AddAvatarToUsers: migrating =================================
-- add_column(:users, :avatar, :string)
   -> 0.0014s
== 20210623060835 AddAvatarToUsers: migrated (0.0017s) ========================

アップローダーの作成→参考

$ rails g uploader avatar  
create  app/uploaders/avatar_uploader.rb

モデルと紐付け

mount_uploader :avatar, ImageUploader
  

uploader.rbの編集

   include CarrierWave::MiniMagick
  def store_dir
    "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
  end

  def default_url(*args)
   'sample.jpg'
  end

  def extension_allowlist
    %w(jpg jpeg gif png)
  end
  

ルーティング

resource :profile, only: %i[show edit update]
  

resourcesとresourceメソッド

プロフィールはユーザーに対して1つしか存在しなく、idを表示させると他のユーザーのプロフィールを編集できてしまうので表示しないように設定。
resourcesではなくresourceを使う。
resourceを使うことでid付きでURLが生成されなくなる。

resourceの場合

edit_profile GET /profile/edit(.:format) profiles#edit
profile GET /profile(.:format) profiles#show
PATCH /profile(.:format) profiles#update
PUT /profile(.:format) profiles#update

resourcesの場合

edit_profile GET /profile/:id/edit(.:format) profile#edit
profile GET /profile/:id(.:format) profile#show
PATCH /profile/:id(.:format) profile#update
PUT /profile/:id(.:format) profile#update

controller

profilesコントローラーの作成

$ rails g controller profiles

ストロングパラメータにavatarを追加。

class ProfilesController < ApplicationController
  def show; end

  def edit
    @user = User.find(current_user.id)
  end

  def update
    @user = User.find(current_user.id)
    if @user.update(user_params)
      redirect_to profile_path, success: 'ユーザーを更新しました'
    else
      flash.now['danger'] = 'ユーザーを更新できませんでした'
      render :edit
    end
  end

  private

  def user_params
    params.require(:user).permit(:email, :first_name, :last_name, :avatar)
  end
end
  

view

プロフィール詳細、編集画面のviewを作成

<% content_for(:title, t('.title')) %>
<div class="container pt-3">
  <div class="row">
    <div class="col-md-10 offset-md-1">
      <h1 class="float-left mb-5"><%= t('.title')%></h1>
      <%= link_to '編集', '/profile/edit', class: 'btn btn-success float-right' %>
      <table class="table">
        <tr>
          <th scope="row">メールアドレス</th>
          <td><%= current_user.email %></td>
        </tr>
        <tr>
          <th scope="row">氏名</th>
          <td><%= current_user.decorate.full_name %></td>
        </tr>
        <tr>
          <th scope="row">アバター</th>
          <td><%= image_tag current_user.avatar.url, class: 'rounded-circle mr15', size: '50x50' %></td>
        </tr>
      </table>
    </div>
  </div>
</div>
  
<% content_for(:title, t('.title')) %>
<div class="container pt-3">
  <div class="row">
    <div class="col-md-10 offset-md-1 mb-5">
      <h1 class="float-left"><%= t('.title')%></h1>
    </div>
    <div class="col-md-10 offset-md-1">
      <%= form_with model: @user, url: profile_path, local: true do |f| %>
        <%= render "shared/error_messages", object: f.object %>
        <div class="form-group">
          <%= f.label :email %>
          <%= f.email_field :email, class: "form-control" %>
        </div>
        <div class="form-group">
          <%= f.label :last_name %>
          <%= f.text_field :last_name, class: "form-control" %>
        </div>
        <div class="form-group">
          <%= f.label :first_name %>
          <%= f.text_field :first_name, class: "form-control" %>
        </div>
        <div class="form-group">
          <%= f.label :avatar %>
          <%= f.file_field :avatar, class: "form-control", accept: 'image/*', onchange: 'previewFileWithId(preview)' %>
          <%= f.hidden_field :avatar_cache %>
          <div class='mt-3 mb-3'>
            <%= image_tag @user.avatar.url , size: '100x100', class: 'rounded-circle' %>
          </div>
        </div>
        <%= f.submit class: "btn btn-primary"%>
      <% end %>  
    </div>
  </div>
</div>
  

ヘッダーアイコン、コメントフォームに設定した画像を表示させる

ヘッダーはログイン中のユーザー

<%= image_tag current_user.avatar_url, size: '40x40', class: 'rounded-circle mr15'%>
  

コメントフォームはコメントしたユーザーのアイコンを表示

<%= image_tag comment.user.avatar_url, class: 'rounded-circle', size: '50x50' %>
  

i18n追記

  profiles:
     edit:
      title: 'プロフィール編集'
     show:
      title: 'プロフィール'
      email: 'メールアドレス'
      name: '氏名'
      avatar: 'アバター'