学生向けプログラミング入門 | 無料

学生向けにプログラミングを無料で解説。Java、C++、Ruby、PHP、データベース、Ruby on Rails, Python, Django

【学習6.0】【MacOSX】画像アップロード(ActiveStorage)

アバター画像をアップロードできるようにします。


コマンド
rails active_storage:install


コマンド マイグレーションの適用
rails db:migrate


「app\models\user.rb」ファイルに記述を追加します。


1.3行目に以下の記述を追加します。

has_one_attached :avatar



2.17行目に以下の記述を追加します。
Googleアカウントでログインした場合、Googleのアカウント画像が表示されるようにしています。

      if !user.provider
        user.update(uid: auth.uid, provider: auth.provider, image: auth.info.image)
      end



記述追加 app\models\user.rb

class User < ApplicationRecord

  has_one_attached :avatar

  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable,
         :confirmable, :omniauthable

  #長さ50文字以下 入力必須
  validates :full_name, presence: true, length: {maximum: 50}

  def self.from_omniauth(auth)
    user = User.where(email: auth.info.email).first
    if user
      if !user.provider
        user.update(uid: auth.uid, provider: auth.provider, image: auth.info.image)
      end    
      return user
    else
      where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
        user.email = auth.info.email
        user.password = Devise.friendly_token[0, 20]
        user.full_name = auth.info.name   # ユーザーモデルに名前があると仮定
        user.image = auth.info.image # ユーザーモデルに画像があると仮定
        user.uid = auth.uid
        user.provider = auth.provider
      end
    end
  end  

end



ユーザーストロングパラメータに「, :avatar」の記述を追加します。


記述追加 app\controllers\users_controller.rb
21行目に「, :avatar」の記述を追加しています。
カンマを忘れないようにして下さい。

class UsersController < ApplicationController

  before_action :authenticate_user!

  def dashboard
  end

  def update
    @user = current_user
    if @user.update_attributes(current_user_params)
      flash[:notice] = "保存しました"
    else
      flash[:alert] = "更新できません"
    end
    redirect_to dashboard_path
  end

  private

  def current_user_params
    params.require(:user).permit(:about, :status, :avatar)
  end
  
end



アバター画像用のヘルパーを追加します。


記述更新 app\helpers\application_helper.rb

module ApplicationHelper
    def avatar_url(user)
        if user.avatar.attached?
            url_for(user.avatar)
        elsif user.image?
            user.image
        else
            ActionController::Base.helpers.asset_path('icon_default_avatar.jpg')
        end
    end    
end



ダッシュボードビューに記述を追加します。


1.14行目の記述を削除します。

<!-- 記述削除 -->
<%= image_tag 'icon_default_avatar.jpg' %>



2.14行目削除した部分に以下の記述を追加します。

<%= image_tag avatar_url(current_user), class: "is-rounded" %>



3.24行目の記述を削除します。

<!-- 記述削除 -->
<button class="button is-primary is-outlined is-fullwidth">アバター画像アップロード</button>



4.24行目の削除した部分に以下の記述を追加します。

<%= form_for :user, url: users_edit_url(@user), action: :update, method: :post do |f| %>
	<div class="file">
		<label class="button is-primary is-outlined is-fullwidth">
			<%= f.file_field :avatar, class: "file-input", onchange: "this.form.submit();" %>
			<i class="fas fa-upload"></i>&nbsp;&nbsp;&nbsp; アバター画像アップロード
		</label>
	</div>
<% end %>   



記述更新 app\views\users\dashboard.html.erb

<section class="section">
    <div class="container">
        <div class="columns">
        
            <!-- 左パネル -->
            <div class="column is-one-third">
                <div class="columns is-multiline">
                    <!-- 上部 -->
                    <div class="column is-full">
                        <div class="card">
                            <!-- アバター -->
                            <div class="card-content is-horizontal-center is-flex">
                                <figure class="image is-256x256">
                                    <%= image_tag avatar_url(current_user), class: "is-rounded" %>
                                </figure>
                            </div>
                            
                            <div class="card-content">
                                <!-- 画像アップロードボタン -->
                                <div class="content has-text-centered">
                                    <p class="title is-5">
                                        <%= current_user.full_name %>
                                    </p>
                                <%= form_for :user, url: users_edit_url(@user), action: :update, method: :post do |f| %>
                                    <div class="file">
                                        <label class="button is-primary is-outlined is-fullwidth">
                                            <%= f.file_field :avatar, class: "file-input", onchange: "this.form.submit();" %>
                                            <i class="fas fa-upload"></i>&nbsp;&nbsp;&nbsp; アバター画像アップロード
                                        </label>
                                    </div>
                                <% end %>   
                                </div>
                                <hr class="h-10">
                                
                                <!-- アカウント情報 -->
                                <article class="media">
                                    <div class="media-content">アカウント登録日</div>
                                    <div class="media-right">
                                        <strong><%= I18n.l(current_user.created_at, format: :full_date) %></strong>
                                    </div>
                                </article>
                                <hr class="h-10">
                                
                                <!-- オンラインステータス -->
                                <article>
                                    <div class="media">
                                        <div class="media-content">ステータス</div>
                                        <div class="media-right">
                                            <strong><% if current_user.status %> オンライン <% else %> オフライン <% end %></strong> <i class="toggle far fa-edit" aria-controls="user-status"></i>
                                        </div>
                                    </div>
                                    <div class="content">
                                        <%= form_for :user, url: users_edit_url(@user), action: :update, method: :post, html: {id: 'user-status', class: 'is-hidden'} do |f| %>
                                            <div class="field">
                                                <%= f.select(:status, options_for_select([["オンライン", true], ["オフライン", false]]), {}, {class: "select is-fullwidth"}) %>
                                            </div>
                                            <a class="toggle button is-light" aria-controls="user-status">キャンセル</a>
                                            <%= f.submit "保存", class: "button is-danger" %>
                                        <% end %>
                                    </div>
                                </article>
                            </div>
                        </div>
                    </div>

                    <!-- 下部 -->
                    <div class="column is-full">
                        <div class="card">
                            <div class="card-content">
                                <!-- アカウント詳細 -->
                                <article>
                                    <div class="media">
                                        <div class="media-content">
                                            <p>
                                                <strong>自己紹介</strong>
                                                <br>
                                                <%= current_user.about %>
                                            </p>
                                        </div>
                                        <div class="media-right">
                                            <i class="toggle far fa-edit" aria-controls="user-about"></i>
                                        </div>
                                    </div>
                                    <div class="content">
                                        <%= form_for :user, url: users_edit_url(@user), action: :update, method: :post, html: {id: 'user-about', class: 'is-hidden'} do |f| %>
                                            <div class="field">
                                                <%= f.text_area :about, autofocus: true, autocomplete: 'form', class: 'input'%>
                                            </div>
                                            <a class="toggle button is-light" aria-controls="user-about">キャンセル</a>
                                            <%= f.submit "保存", class: "button is-danger" %>
                                        <% end %>
                                    </div>
                                </article>
                                <hr class="h-10">
                                
                                <!-- アカウント連携 -->
                                <article class="media">
                                    <div class="content">
                                        <p>
                                            <strong>アカウント連携</strong><br/>
                                            <% if current_user.provider == 'google_oauth2' %>
                                                <span class="has-text-success">Googleアカウントでログイン中</span>
                                            <% else %>
                                                <span class="has-text-danger">アカウント連携していません</span>
                                            <% end %>
                                        </p>
                                    </div>
                                </article>
                            </div>
                        </div>
                    </div>
                </div>
            </div>

            <!-- 右側 -->
            <div class="column">
                <div class="columns is-multiline">
                    <!-- 購入したプロジェクト -->
                    <div class="column is-one-third has-text-centered">
                    
                    </div>
                </div>
            </div>
            
        </div>
    </div>
</section>



ナビゲーションバーを更新します。


記述追加 app\views\shared\_navbar.html.erb(32行目)

<figure class="image is-48x48 m-r-5">
    <div style="margin-top: 0.6rem;">
      <%= image_tag avatar_url(current_user), class: "is-rounded" %>
    </div>
</figure>



app\views\shared\_navbar.html.erb

<nav class="navbar is-link" role="navigation" aria-label="main navigation">

    <div class="navbar-brand">
        <a class="navbar-item" href="/">
            <h1>テストサイトGakushuu6</h1>
        </a>
        <a role="button" class="navbar-burger burger" aria-label="menu" aria-expanded="false" data-target="navbarBasicExample">
            <span aria-hidden="true"></span>
            <span aria-hidden="true"></span>
            <span aria-hidden="true"></span>
        </a>
    </div>

    <div id="navbarBasicExample" class="navbar-menu">

        <div class="navbar-end">
            <a class="navbar-item"></a>
            <a class="navbar-item"></a>

            <!-- もしログインしていなかったら-->
            <% if (!user_signed_in?) %>
                <div class="navbar-item">
                    <div class="buttons">
                        <%= link_to  "新規ユーザ登録", new_user_registration_path, class: "button is-info" %>
                        <%= link_to  "ログイン", new_user_session_path, class: "button is-light" %>
                    </div>
                </div>

            <!-- ログインしていたら -->
            <% else %>
                <div class="navbar-item has-dropdown is-hoverable" style="margin-right: 100px;">
                    <figure class="image is-48x48 m-r-5">
                        <div style="margin-top: 0.6rem;">
                        <%= image_tag avatar_url(current_user), class: "is-rounded" %>
                        </div>
                    </figure>                
                    <a class="navbar-item"><%= current_user.full_name %>
                    <i class="far fa-caret-square-down"></i>
                    </a>
                    <div class="navbar-dropdown">
                        <%= link_to 'ダッシュボード', dashboard_path, class: "navbar-item" %>
                        <%= link_to  "ユーザ登録情報編集", edit_user_registration_path, class: "navbar-item" %>
                        <hr class="navbar-divider">
                        <%= link_to  "ログアウト", destroy_user_session_path, method: :delete, class: "navbar-item" %>
                    </div>
                </div>
            <% end %>

        </div>
    </div>
</nav>

<% if (user_signed_in?) %>
    <nav class="navbar has-shadow" style="z-index: 5;">
        <div class="container">
            <div class="navbar">

                <%= link_to 'ダッシュボード', dashboard_path, class: "navbar-item" %>

                <div class="navbar-item has-dropdown is-hoverable">
                    <a class="navbar-link">メニュー</a>
                    <div class="navbar-dropdown">
                    <a class="navbar-item"></a>
                    <hr class="navbar-divider">
                    <%= link_to  "ユーザ登録情報編集", edit_user_registration_path, class: "navbar-item" %>
                    </div>
                </div>

            </div>
        </div>
    </nav>
<% end %>

<script>
$(document).ready(function() {
  // navbar burgerアイコンでクリックイベントを確認する
  $(".navbar-burger").click(function() {
      // 「navbar-burger」と「navbar-menu」の両方で「is-active」クラスを切り替えます
      $(".navbar-burger").toggleClass("is-active");
      $(".navbar-menu").toggleClass("is-active");
  });
});
</script>



ブラウザ確認
http://localhost:3000/dashboard


ドロップダウンメニューにアバター画像をつけました。

アバター画像
アバター画像



アバター画像をアップロードできるか確認して下さい。

アップロード確認
アップロード確認

YAE C5 CLINIC(札幌美容クリニック)

関連記事(外部サイト)