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

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

Ruby on Rails6.0 | 空き部屋を登録・予約・決済できるWebサイトを作成する 15 | 画像アップロード(ActiveStorage)

[14]Gitにコミット<< [ホームに戻る] >> [16]アマゾンS3


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


コマンド
rails g migration AddImageColumsToUser image


コマンド
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,
         :confirmable

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



ユーザ情報の書き換えに制限をかけるため、permitに「, :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.16行目の「<%= image_tag 'icon_default_avatar.jpg' %>」の記述を以下の記述に書き換えます。

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



2.記述追加 app\views\users\dashboard.html.erb(27行目)
26行目の記述を削除して置き換えます。

<%= 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">
                                </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>



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


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

<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-light" role="navigation" aria-label="main navigation">
    <div class="navbar-brand">
        <a class="navbar-item" href="/">
            <h1>テストサイトMinpaku6</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>
        </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-white" %>
                        <%= link_to  "ログイン", new_user_session_path, class: "button is-white" %>
                    </div>
                </div>

            <!-- ログインしていたら -->
            <% else %>
                <div class="navbar-item has-dropdown is-hoverable" style="margin-right: 100px;">
                    <a class="navbar-item">
                        <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  "ユーザ登録情報編集", edit_user_registration_path, class: "navbar-item" %>
                        <a href="" class="navbar-item"></a>
                        <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: 3;">
        <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() {
    // 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


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

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



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

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


[14]Gitにコミット<< [ホームに戻る] >> [16]アマゾンS3