りゅうじの学習blog

学習したことをアウトプットしていきます。

AdminLTE 3を使って管理者ページを実装しよう・2

この記事の続きです。

https://ryujisurf55.hatenablog.com/entry/2021/04/30/180846

手順

  1. 管理者用のコントローラーを作成
  2. ルーティングの設定
  3. ビューの設定
  4. ページタイトルの設定

1.管理者用のコントローラーを作成

まずはベースとなるadmin/base_controller.rb を作成します。

#ターミナル

$ rails g controller admin::base
#app/controllers/admin/base_controller.rb

class Admin::BaseController < ApplicationController
   before_action :check_admin
   layout 'admin/layouts/application'
 
   private
 
   def not_authenticated
     flash[:warning] = 'ログインして下さい'
     redirect_to admin_login_path
   end
 
   def check_admin
     redirect_to root_path, warning: '権限がありません' unless current_user.admin?
   end
 end

layout で読み込みたいレイアウトを指定しています。このレイアウトは後で作成します。

check_adminメソッド で管理者でない場合はトップページに遷移するようにしています。

次はこのbase_controller を継承したログイン機能を有したコントローラーuser_sessions.rb とトップーページの遷移を管理するdashboards_controller.rb も作成していきます。

#ターミナル

$ rails g controller admin::user_sessin

$ rails g controller admin::dashboards
#app/controllers/admin/user_sessions_controller.rb

class Admin::UserSessionsController < Admin::BaseController
  skip_before_action :check_admin, only: %i[new create]
  skip_before_action :require_login, only: %i[new create]
  layout 'admin/layouts/admin_login'

  def new; end

  def create
    @user = login(params[:email], params[:password])
    if @user
      redirect_to admin_root_path, success: 'ログインしました'
    else
      flash.now[:danger] = 'ログインに失敗しました'
      render :new
    end
  end

  def destroy
    logout
    redirect_to admin_login_path, success: 'ログアウトしました'
  end
end

これは管理者用のログイン画面です。

つまりログインしていない状態でもアクセスを可能にする必要があり

skip_before_action を指定しているわけです。

#app/controllers/admin/dashboards_controller.rb

class Admin::DashboardsController < Admin::BaseController
   def index; end
end

継承元のbase_controller.rb でレイアウトファイルを指定しているのでここでは指定しません。

2.ルーティングの設定

#config/routes.rb

namespace :admin do
     root to: 'dashboards#index'
     get 'login', to: 'user_sessions#new'
     post 'login', to: 'user_sessions#create'
     delete 'logout', to: 'user_sessions#destroy'
   end

namespace

以下の場合はnamespaceが望ましい

  • URLは指定のパスにしたい
  • ファイル構成も指定のパスにしたい

今回のadmin ではこちらが当てはまる為使用します。

/admin から始まるURLにする事ができて分けて管理する事ができます。

3.ビューの設定

まずはレイアウトの作成

ディレクトリを作成とファイルの作成。

#ターミナル

$ mkdir app/views/layouts

$ touch app/views/layouts/application.html.erb

$ touch app/views/layouts/admin_login.html.erb
#app/views/layouts/application.html.erb

<!DOCTYPE html>
 <html>
 <head>
   <meta charset="UTF-8">
   <meta lang='ja'>
   <meta name="robots" content="noindex, nofollow">
   <title><%= page_title(yield(:title), admin: true) %></title>
   <%= csrf_meta_tags %>
   <%= stylesheet_link_tag 'admin', media: 'all' %> #ここでadmin.scssを読み込む
   <link href="<https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,400i,700>" rel="stylesheet">
 </head>
 
 <body class="hold-transition sidebar-mini layout-fixed">
 <div class="wrapper">
 
   <%= render 'admin/shared/header' %>
   <%= render 'admin/shared/sidebar' %>
 
   <!-- Content Wrapper. Contains page content -->
   <div class="content-wrapper">
     <%= render 'shared/flash_message' %>
     <%= yield %>
   </div>
   <!-- /.content-wrapper -->
 
   <%= render 'admin/shared/footer' %>
 
 </div>
 <%= javascript_include_tag 'admin' %> #ここでadmin.jsを読み込む
 </body>
 </html>
#app/views/layouts/admin_login.html.erb

<!DOCTYPE html>
 <html>
 <head>
   <meta charset="utf-8">
   <meta http-equiv="X-UA-Compatible" content="IE=edge">
   <meta name="robots" content="noindex, nofollow">
   <title><%= page_title(yield(:title), admin: true) %></title>
   <meta name="viewport" content="width=device-width, initial-scale=1">
   <%= csrf_meta_tags %>
   <%= stylesheet_link_tag 'admin', media: 'all' %> #ここでadmin.scssを読み込む
 </head>
 <body class="hold-transition login-page">
   <div>
     <%= render 'shared/flash_message' %>
     <%= yield %>
   </div>
 </body>
 </html>

ヘッダー・サイドバー・フッターのパーシャルを作成

admin/shared ディレクトリを作成してパーシャルを作ります。

#ターミナル

$ mkdir app/views/admin/shared

$ touch app/views/admin/shared/_header.html.erb

$ touch app/views/admin/shared/_sidebar.html.erb

$ touch app/views/admin/shared/_footer.html.erb
#app/views/admin/shared/_header.html.erb

<!-- Navbar -->
 <nav class="main-header navbar navbar-expand navbar-white navbar-light">
   <!-- Left navbar links -->
   <ul class="navbar-nav">
     <li class="nav-item">
       <a class="nav-link" data-widget="pushmenu" href="#"><i class="fas fa-bars"></i></a>
     </li>
   </ul>
 
   <!-- Right navbar links -->
   <ul class="navbar-nav ml-auto">
     <li class="nav-item">
       <%= link_to t('defaults.logout'), admin_logout_path, class: 'nav-link', method: :delete %>
     </li>
   </ul>
 </nav>
 <!-- /.navbar -->
#app/views/admin/shared/_sidebar.html.erb

<!-- Main Sidebar Container -->
 <aside class="main-sidebar sidebar-dark-primary elevation-4">
   <!-- Brand Logo -->
   <a href="index3.html" class="brand-link">
     <%= image_tag 'AdminLTELogo.png', class: 'brand-image img-circle elevation-3' %>
     <span class="brand-text font-weight-light">AdminLTE 3</span>
   </a>
 
   <!-- Sidebar -->
   <div class="sidebar">
     <!-- Sidebar user panel (optional) -->
     <div class="user-panel mt-3 pb-3 mb-3 d-flex">
       <div class="image">
         <%= image_tag current_user.avatar_url, class: 'img-circle elevation-2' %>
       </div>
       <div class="info">
         <a href="#" class="d-block"><%= current_user.decorate.full_name %></a>
       </div>
     </div>
 
     <!-- Sidebar Menu -->
     <nav class="mt-2">
       <ul class="nav nav-pills nav-sidebar flex-column" data-widget="treeview" role="menu" data-accordion="false">
         <li class="nav-item">
           <%= link_to '#', class: "nav-link" do %>
             <i class="nav-icon far fa-file"></i>
             <p>
               掲示板
             </p>
           <% end %>
         </li>
         <li class="nav-item">
           <%= link_to '#', class: "nav-link" do %>
             <i class="nav-icon far fa-user"></i>
             <p>
               ユーザー
             </p>
           <% end %>
         </li>
       </ul>
     </nav>
     <!-- /.sidebar-menu -->
   </div>
   <!-- /.sidebar -->
 </aside>
#app/views/admin/shared/_footer.html.erb

<footer class="main-footer">
   <strong>Copyright &copy; 2019 RUNTEQ.</strong>
   All rights reserved.
</footer>

ここまででレイアウトとパーシャルができました。

ログイン画面とトップページの作成

#ターミナル

$ app/admin/user_sessions/new.html.erb

$ app/admin/dashboards/index.html.erb
#app/admin/user_sessions/new.html.erb

<% content_for(:title, 'ログイン') %>
 <div class="login-box">
   <div class="login-logo">
     <h1>ログイン</h1>
   </div>
   <!-- /.login-logo -->
   <div class="card">
     <div class="card-body login-card-body">
 
       <%= form_with url: admin_login_path, local: true do |f| %>
         <%= f.label :email, 'メールアドレス' %>
         <div class="input-group mb-3">
           <%= f.text_field :email, class: 'form-control', placeholder: 'メールアドレス' %>
           <div class="input-group-append">
             <div class="input-group-text">
               <span class="fas fa-envelope"></span>
             </div>
           </div>
         </div>
 
         <%= f.label :password, User.human_attribute_name(:password) %>
         <div class="input-group mb-3">
           <%= f.password_field :password, class: 'form-control', placeholder: :password %>
           <div class="input-group-append">
             <div class="input-group-text">
               <span class="fas fa-lock"></span>
             </div>
           </div>
         </div>
 
         <div class="row">
           <div class="col-12">
             <%= f.submit (t 'defaults.login'), class: 'btn btn-block btn-primary' %>
           </div>
         </div>
       <% end %>
     </div>
   </div>
 </div>
#app/admin/dashboards/index.html.erb

<% content_for(:title, 'ダッシュボード') %>
 <div class="container">
   <div class="row">
     ダッシュボードです
   </div>
 </div>

4.ページタイトルの設定

ページタイトルの設定は過去記事で触れているので宜しければ。

https://ryujisurf55.hatenablog.com/entry/2021/04/27/184802

#app/helpers/application_helper.rb

module ApplicationHelper
   def page_title(page_title = '', admin = false)
     base_title = if admin
                    'RUNTEQ BOARD APP(管理画面)'
                  else
                    'RUNTEQ BOARD APP'
                  end
 
     page_title.empty? ? base_title : page_title + ' | ' + base_title
   end

最後に

読んでいただいた方、ありがとうございました。