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

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

Rails7.1 | 動画学習アプリ作成 | 07 | ログイン機能の実装

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



06 | ナビゲーションバーの利用】 << 【ホーム】 >> 【08 | 日本語化



deviceによるログイン機能をビューも含めて実装していきます。
まずはユーザーモデルに氏名の項目を追加します。


ユーザーテーブルにfull_nameフィールドを追加します。
コマンド
rails g migration AddFullnameToUser full_name:string


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

full_nameフィールドの確認
full_nameフィールドの確認



posticoを起動し、テストで登録したユーザーを削除します。
フィールドに項目を追加した場合、データ削除しないとログインページなどが表示されなくなります。


ユーザモデルにバリデーションを追加します。


記述追加 app\models\user.rb(3行目)

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



app\models\user.rb

class User < ApplicationRecord

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

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



許可パラメータを追加します。
これによって「permitted_parameters」で許可されたパラメータのみ変更が可能となります。
「app\controllers\application_controller.rb」ファイルを以下のように更新して下さい。


記述更新 app\controllers\application_controller.rb

class ApplicationController < ActionController::Base

    before_action :configure_permitted_parameters, if: :devise_controller?

    protected

    def configure_permitted_parameters
        devise_parameter_sanitizer.permit(:sign_up, keys: [:full_name])
        devise_parameter_sanitizer.permit(:account_update, keys: [:full_name])
    end
    
end



ルートを設定します。
localhost:3000/にアクセスすればpages/homeに自動でジャンプするように設定します。
また、deviceのpath_nameを変更します。
「config/routes.rb」ファイルに以下の記述を追加します。

  # ルートを app\views\pages\home.html.erb に設定
  root 'pages#home'


 # device
  devise_for :users, 
              path: '', 
              path_names: {sign_up: 'register', sign_in: 'login', edit: 'profile', sign_out: 'logout'}



記述編集 【config/routes.rb】

Rails.application.routes.draw do

  # ルートを app\views\pages\home.html.erb に設定
  root 'pages#home'

  # get
  get 'pages/home'

  # device
  devise_for :users, 
              path: '', 
              path_names: {sign_up: 'register', sign_in: 'login', edit: 'profile', sign_out: 'logout'}
  # Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html

  # Reveal health status on /up that returns 200 if the app boots with no exceptions, otherwise 500.
  # Can be used by load balancers and uptime monitors to verify that the app is live.
  get "up" => "rails/health#show", as: :rails_health_check

  # Defines the root path route ("/")
  # root "posts#index"
end



ホームページのナビゲーションバーを更新します。


記述更新 app\views\shared\_navbar.html.erb

<nav class="navbar navbar-expand-lg bg-body-tertiary">
  <div class="container-fluid">
    <a class="navbar-brand" href="/">StreamAcademe</a>
    <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
      <span class="navbar-toggler-icon"></span>
    </button>
    <div class="collapse navbar-collapse" id="navbarSupportedContent">
      <ul class="navbar-nav me-auto mb-2 mb-lg-0">
        <!-- もしログインしていなかったら-->
        <% if (!user_signed_in?) %>
        <li class="nav-item" style="margin-bottom: 0.1rem;">
          <span style="margin-left: 1rem;">
          <%= link_to  "新規登録", new_user_registration_path, class: "btn btn-danger" %>
          </span>
        </li>
        <li class="nav-item">
          <span style="margin-left: 1rem;">
            <%= link_to  "ログイン", new_user_session_path, class: "btn btn-success text-light" %>
          </span>
        </li>
      </ul>
      <!-- ログインしていたら -->
      <% else %>
      <ul class="navbar-nav" style="margin-left: 2rem;">
        <li class="nav-item dropdown">
          <a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
            ドロップダウン<%= current_user.full_name %>
          </a>
          <ul class="dropdown-menu">
            <li><%= link_to  "ユーザ登録情報編集", edit_user_registration_path, class: "dropdown-item btn btn-light" %></li>
            <li><hr class="dropdown-divider"></li>
            <li><%= button_to  "ログアウト", destroy_user_session_path, method: :delete, class: "dropdown-item btn btn-light" %></li>
          </ul>
        </li>
      </ul>
      <% end %>
    </div>
  </div>
</nav>



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

PCレイアウト
PCレイアウト


モバイルレイアウト
モバイルレイアウト



認証ビューを更新します。


記述更新 app\views\devise\registrations\new.html.erb

<div class="container px-4 mt-2">
  <div class="card w-100 mb-3">
    <div class="card-body">
      <h5 class="card-title text-danger h3"><strong><span>新規登録</span></strong></h5>
      <p class="card-text"><strong>ユーザー登録をお願いします。</p>

      <%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>  
        <div class="mb-5 mt-5">
          <label for="exampleInputEmail1">氏名</label>
          <%= f.text_field :full_name, autofocus: true, placeholder: "氏名", class: "form-control" %>
          <div id="emailHelp" class="form-text">氏名を必ず登録しましょう。</div>
        </div>

        <div class="mb-5">
          <label for="exampleInputEmail1">Eメールアドレス</label>
          <%= f.email_field :email, autofocus: true, placeholder: "Eメールアドレス", class: "form-control" %>
          <div id="emailHelp" class="form-text">メールアドレスは必須です。</div>
        </div>

        <div class="mb-3">
          <label for="exampleInputEmail1" class="ttl">パスワード</label>
          <%= f.password_field :password, autocomplete: "off", placeholder: "パスワード", class: "form-control" %>
          <div id="emailHelp" class="form-text">強力なセキュリティを確保するために、最低でも6文字以上のパスワードが必要です。</div>
        </div>          

        <div class="mb-5">
          <label for="exampleInputEmail1" class="ttl">パスワード確認</label>
          <%= f.password_field :password_confirmation, autocomplete: "off", placeholder: "パスワード確認", class: "form-control" %>
          <div id="emailHelp" class="form-text">パスワード確認: 確認のため、入力したパスワードをもう一度入力してください。同じパスワードを入力する必要があります。</div>
        </div>        
        <%= f.submit "登録", class: "btn btn-danger w-100" %>
      <% end %>

      <div class="mt-4">
        <%= render "devise/shared/links" %>
      </div>
    </div>
  </div>

  <!--  SNS認証 -->
  <div class="card w-100 mb-5">
    <div class="card-body">
      <h5 class="card-title text-dark h6">下記サービスアカウントでの登録はこちら</h5>
  </div>    
</div>



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

PCレイアウト
PCレイアウト


モバイルレイアウト
モバイルレイアウト



セッションビューの編集をします。
ログイン画面の見た目の編集です。


記述更新 app\views\devise\sessions\new.html.erb

<div class="container">
  <div class="row gx-5">
    <div class="col">
      <div class="card w-100 mb-3">
        <div class="card-body">
          <h5 class="card-title text-danger h3"><strong><span class="ttl">ログイン</span></strong></h5>
          <p class="card-text">作成したアカウントでログインしてください。</p>
          <%= form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| %>      
            <div class="mb-5 mt-5">
            <div class="mb-5">
              <label for="exampleInputEmail1" class="ttl">Eメールアドレス</label>
              <%= f.email_field :email, autofocus: true, placeholder: "Eメールアドレス", class: "form-control" %>
              <div id="emailHelp" class="form-text">あなたのメールは他の誰とも共有しません。</div>
            </div>
            <div class="mb-5">
              <label for="exampleInputEmail1" class="ttl">パスワード</label>
              <%= f.password_field :password, autocomplete: "off", placeholder: "パスワード", class: "form-control" %>
              <div id="emailHelp" class="form-text">登録した6文字以上のパスワード入力が必要です。</div>
            </div>          
            <% if devise_mapping.rememberable? %>
            <div class="field mb-5">
              <%= f.check_box :remember_me %>
              ログインを保持
            </div>
            <% end %>            
            <%= f.submit "ログイン", class: "btn btn-danger w-100" %>
          <% end %>
          <div class="mt-4">
            <%= render "devise/shared/links" %>
          </div>
        </div>
      </div>
    </div>
    <div class="col">
      <div class="card w-100 mb-5">
        <div class="card-body">
          <h5 class="card-title text-dark h6">下記サービスアカウントでのログインはこちら</h5>      
        </div>
      </div>        
    </div>
  </div>
</div>



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

PCレイアウト
PCレイアウト


モバイルレイアウト
モバイルレイアウト



パスワードを入力しなくても情報を更新できるよう、コントローラーを作成します。


「app/controllers」フォルダに「registrations_controller.rb」ファイルを新規作成します。
作成した「registrations_controller.rb」ファイルを以下のように編集します。



新規作成 【app/controllers/registrations_controller.rb】

class RegistrationsController < Devise::RegistrationsController
    
    protected
    def update_resource(resource, params)
        resource.update_without_password(params)
    end
end



作成したコントローラーをルートに追加します。
追加する記述は以下の通りです。

  # device
  devise_for :users, 
              path: '', 
              path_names: {sign_up: 'register', sign_in: 'login', edit: 'profile', sign_out: 'logout'},
              controllers: {registrations: 'registrations'}



記述追加 【config/routes.rb】9行目

Rails.application.routes.draw do

  # ルートを app\views\pages\home.html.erb に設定
  root 'pages#home'

  # get
  get 'pages/home'

  # device
  devise_for :users, 
              path: '', 
              path_names: {sign_up: 'register', sign_in: 'login', edit: 'profile', sign_out: 'logout'},
              controllers: {registrations: 'registrations'}
  # Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html

  # Reveal health status on /up that returns 200 if the app boots with no exceptions, otherwise 500.
  # Can be used by load balancers and uptime monitors to verify that the app is live.
  get "up" => "rails/health#show", as: :rails_health_check

  # Defines the root path route ("/")
  # root "posts#index"
end



アカウント情報編集ページを更新します。


記述更新 app\views\devise\registrations\edit.html.erb

<div class="container">
  <div class="card w-100 mb-3">
    <div class="card-body">
      <h5 class="card-title text-danger h3"><strong><span class="ttl">ユーザ情報編集</span></strong></h5>
      <p class="card-text">変更があったら情報を更新しましょう。</p>

      <%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put }) do |f| %>
        <%= render "devise/shared/error_messages", resource: resource %>      
        <div class="mb-3">
          <label for="exampleInputEmail1" class="ttl">氏名</label>
          <%= f.text_field :full_name, autofocus: true, placeholder: "氏名", class: "form-control" %>
          <div id="emailHelp" class="form-text">氏名</div>
        </div>

        <div class="mb-4">
          <label for="exampleInputEmail1" class="ttl">Eメールアドレス</label>
          <%= f.email_field :email, autofocus: true, placeholder: "Eメールアドレス", class: "form-control" %>
          <div id="emailHelp" class="form-text">あなたのメールは他の誰とも共有しません。</div>
        </div>
        <% if devise_mapping.confirmable? && resource.pending_reconfirmation? %>
          <div>現在、次の確認を待っています:<%= resource.unconfirmed_email %></div>
        <% end %>

        <div class="mb-3">
          <label for="password" class="ttl">変更パスワード</label>
          <%= f.password_field :password, autocomplete: "off", placeholder: "パスワード", class: "form-control", id: "password" %>
          <div id="emailHelp" class="form-text">強力なセキュリティを確保するために、最低でも6文字以上のパスワードが必要です。</div>
        </div>          

        <div class="mb-5">
          <label for="confirmation" class="ttl">変更パスワード(確認)</label>
          <%= f.password_field :password_confirmation, autocomplete: "off", placeholder: "確認パスワード", class: "form-control", id: "confirmation" %>
          <div id="emailHelp" class="form-text">パスワード確認: 確認のため、入力したパスワードをもう一度入力してください。同じパスワードを入力する必要があります。</div>
        </div>
    
        <div class="mb-2">
        <%= f.submit "更新", class: "btn btn-danger w-100" %>
        </div>

      <% end %>
      <div class="mb-5">
      <%= link_to "戻る", :back, class: "btn btn-secondary w-100" %>
      </div>
    </div>
  </div>
</div>



ブラウザ確認
ログインしておく必要があります。


http://localhost:3000/profile

PCレイアウト
PCレイアウト


モバイルレイアウト
モバイルレイアウト



デバイスのレンダーファイルを更新します。


記述更新 app\views\devise\shared\_links.html.erb

<div class="all" style="text-align: left;">
  <%- if controller_name != 'sessions' %>
    <font style="font-size:0.9rem;">
      ユーザ登録がお済みの方は<%= link_to "ログイン", new_session_path(resource_name), class: "btn btn-outline-secondary btn-sm" %>してください。<br />
      登録ボタンを押すとメールが送信されます。</br>
      メールに記載されているリンクをクリックするとアカウントが有効化されます。<br/>
    </font>
  <% end %>
  <%- if devise_mapping.registerable? && controller_name != 'registrations' %>
    <font style="font-size:0.9rem;">
      <%= link_to "新規ユーザ登録", new_registration_path(resource_name), class: "btn btn-outline-secondary btn-sm" %>がお済みでない方は先に登録をお願い致します。
    </font>
  <% end %>
  <br/>
  <%- if devise_mapping.recoverable? && controller_name != 'passwords' && controller_name != 'registrations' %>
    <br/>
    <%= link_to "パスワードをお忘れですか?", new_password_path(resource_name), class: "btn btn-outline-secondary btn-sm" %><br />
  <% end %>
  <%- if devise_mapping.confirmable? && controller_name != 'confirmations' %>
    <br/>
    <%= link_to "確認のメールが届かない方はこちら", new_confirmation_path(resource_name), class: "btn btn-outline-secondary btn-sm" %><br />
  <% end %>
  <%- if devise_mapping.lockable? && resource_class.unlock_strategy_enabled?(:email) && controller_name != 'unlocks' %>
    <%= link_to "ロック解除の手順を受け取っていませんか?", new_unlock_path(resource_name), class: "btn btn-outline-secondary btn-sm" %><br />
  <% end %>
</div>



パスワードリセットのビューを更新します。


記述更新 app\views\devise\passwords\new.html.erb

<div class="container px-4">
  <div class="card w-100 mb-5">
    <div class="card-body">
      <h5 class="card-title text-danger h3"><strong>パスワードをお忘れですか?</strong></h5>
      <p class="card-text">心配ご無用です。入力したメールアドレスに、パスワードリセット用のリンクが送信されます。</p>

      <%= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :post }) do |f| %>
        <%= render "devise/shared/error_messages", resource: resource %>

        <div class="mb-5">
          <label for="exampleInputEmail1" class="form-label">Eメールアドレス</label>
          <%= f.email_field :email, autofocus: true, autocomplete: "メールアドレス", placeholder: "Eメールアドレス", class: "form-control" %>
          <div id="emailHelp" class="form-text">あなたのメールは他の誰とも共有しません。</div>
        </div>
      
        <div class="mb-2">
        <%= f.submit "パスワード リセット", class: "btn btn-danger w-100" %>
        </div>
        <div class="mb-5">
          <%= link_to "戻る", :back, class: "btn btn-secondary w-100" %>
        </div>

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



ブラウザ確認
ログアウトしておく必要があります。
http://localhost:3000/password/new

PCレイアウト
PCレイアウト


モバイルレイアウト
モバイルレイアウト



パスワード変更のビューを更新します。
メール送信設定を行なった後でなければ確認できませんが変更しておきます。


app\views\devise\passwords\edit.html.erb

<div class="container px-4">
  <div class="card w-100 mb-5">
    <div class="card-body">
      <h5 class="card-title text-danger h3"><strong>パスワード変更</strong></h5>
      <p class="card-text">新しいパスワードを入力してください。安全な新しいパスワードを作成し、それを入力します。パスワードは少なくとも6文字以上で、大文字と小文字、数字、特殊文字を組み合わせることをお勧めします。</p>

      <%= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :put }) do |f| %>
        <%= render "devise/shared/error_messages", resource: resource %>
        <%= f.hidden_field :reset_password_token %>

        <div class="mb-3">
          <label for="exampleInputEmail1" class="form-label">変更パスワード</label>
          <%= f.password_field :password, autocomplete: "off", placeholder: "パスワード", class: "form-control" %>
          <div id="emailHelp" class="form-text">強力なセキュリティを確保するために、最低でも6文字以上のパスワードが必要です。</div>
        </div>          

        <div class="mb-5">
          <label for="exampleInputEmail1" class="form-label">変更パスワード(確認)</label>
          <%= f.password_field :password_confirmation, autocomplete: "off", placeholder: "パスワード", class: "form-control" %>
          <div id="emailHelp" class="form-text">パスワード確認: 確認のため、入力したパスワードをもう一度入力してください。同じパスワードを入力する必要があります。</div>
        </div>
      
        <div class="mb-5">
          <%= f.submit "パスワードを変更する", class: "btn btn-danger btn-block" %>
        </div>

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



これでDeviceによるログイン機能の実装が終わりました。



06 | ナビゲーションバーの利用】 << 【ホーム】 >> 【08 | 日本語化





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