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

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

Rails6.0 | 仕事売買サイトの構築 | 15 | 画像アップロード(ActiveStorage)

[14]GitHubとの同期 << [ホームに戻る] >> [16]アマゾンS3


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


コマンド
rails active_storage:install


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


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


記述追加 app\models\user.rb
3行目に「has_one_attached :avatar」の記述を追加しています。

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, 
         :omniauthable, :confirmable

  validates :full_name, presence: true, length: {maximum: 50}      

  def self.from_omniauth(auth)
    user = User.where(email: auth.info.email).first

    if user
      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(:from, :about, :status, :language, :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.記述削除 app\views\users\dashboard.html.erb(14行目)

<%= image_tag 'icon_default_avatar.jpg' %>



2.記述追加 app\views\users\dashboard.html.erb(14行目)
削除した場所に以下の記述を貼り付けます。

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



3.記述削除 app\views\users\dashboard.html.erb(24行目)

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



4.記述追加 app\views\users\dashboard.html.erb(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><%= current_user.from %></strong> <i class="toggle far fa-edit" aria-controls="user-from"></i>
                                        </div>
                                    </div>
                                    <div class="content">
                                        <%= form_for :user, url: users_edit_url(@user), action: :update, method: :post, html: {id: 'user-from', class: 'is-hidden'} do |f| %>
                                            <div class="field">
                                                <%= f.text_field :from, autofocus: true, autocomplete: 'form', class: 'input'%>
                                            </div>
                                            <a class="toggle button is-light" aria-controls="user-from">キャンセル</a>
                                            <%= f.submit "保存", class: "button is-danger" %>
                                        <% end %>
                                    </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>
                                    <div class="media">
                                        <div class="media-content">
                                            <p>
                                                <strong>言語</strong>
                                                <br>
                                                <%= current_user.language %>
                                            </p>
                                        </div>
                                        <div class="media-right">
                                            <i class="toggle far fa-edit" aria-controls="user-language"></i>
                                        </div>
                                    </div>

                                    <div class="content">
                                        <%= form_for :user, url: users_edit_url(@user), action: :update, method: :post, html: {id: 'user-language', class: 'is-hidden'} do |f| %>
                                            <div class="field">
                                                <%= f.text_field :language, autofocus: true, autocomplete: 'form', class: 'input'%>
                                            </div>
                                            <a class="toggle button is-light" aria-controls="user-language">キャンセル</a>
                                            <%= f.submit "保存", class: "button is-danger" %>
                                        <% end %>
                                    </div>
                                </article>
                                <hr class="h-10">
                                
                                <!-- アカウント連携 -->
                                <article class="media">
                                </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 class="column is-one-third has-text-centered"></div>
                    
                </div>
            </div>
            
        </div>
    </div>
</section>



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


1.記述削除 app\views\shared\_navbar.html.erb(43行目)

<a class="navbar-item" style="margin-right: 50px;"><%= current_user.full_name %></a>



記述追加 app\views\shared\_navbar.html.erb(43行目)
削除した場所に以下の記述を追加します。

<a class="navbar-item" style="margin-right: 50px;">
    <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>                                        
    <%= current_user.full_name %>
</a>



app\views\shared\_navbar.html.erb

<nav class="navbar is-danger" role="navigation" aria-label="main navigation">
    <div class="navbar-brand">
        <a class="navbar-item" href="/">
            <h1>テストサイトOshigoto</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-start">
            <div class="navbar-item">
                <div class="field has-addons">
                    <div class="control">
                        <input class="input" type="text" placeholder="どんなお仕事を?">
                    </div>
                    <div class="control">
                        <a class="button is-success">検索</a>
                    </div>
                </div>
            </div>
        </div>
        <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-primary" %>
                        <%= link_to  "ログイン", new_user_session_path, class: "button is-light" %>
                    </div>
                </div>

            <!-- ログインしていたら -->
            <% else %>
                <div class="navbar-item has-dropdown is-hoverable">

                    <a class="navbar-item" style="margin-right: 50px;">
                        <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>                                        
                        <%= current_user.full_name %>
                    </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>
                        <a class="navbar-item"></a>
                    </div>
                </div>
                <div class="navbar-item has-dropdown is-hoverable">
                    <a class="navbar-link">お仕事を買う人</a>
                    <div class="navbar-dropdown">
                        <a class="navbar-item"></a>
                        <a class="navbar-item"></a>
                    </div>
                </div>
            </div>
        </div>
    </nav>
<% end %>

<script>
$(document).ready(function() {
  // Check for click events on the navbar burger icon
  $(".navbar-burger").click(function() {
      // Toggle the "is-active" class on both the "navbar-burger" and the "navbar-menu"
      $(".navbar-burger").toggleClass("is-active");
      $(".navbar-menu").toggleClass("is-active");
  });
});
</script>



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


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

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


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


↓↓クリックして頂けると励みになります。


[14]GitHubとの同期 << [ホームに戻る] >> [16]アマゾンS3