AdminLTE 3を使って簡単な管理者ページを実装

どうもどハマりエンジニアです。

 

本日は管理画面へのログイン機能、管理画面トップページの作成 を作成していきます。

 

 

AdminLTE3のインストール

まず今回はyarnを使ってAdminLTEをインストールしていきます。

yarnとはJavaScriptのパッケージマネージャーのことで、yarnとnpmの2種類ありますが、今回はyarnを使っていきます。

$yarn add admin-lte

これでこれでnode_modulespackage.jsonyarn.lockというファイルがインストールされます。 node_modules/admin-lteディレクトリにデフォルトテンプレートが記載されているので今回はその中のstarter.htmlとlogin.htmlを使っていきます。

 

管理者ページ用のマニフェストファイルを作成

今回は一般ページと管理者ページでは見た目が大きく変わってくるので、一般ページと分けて管理者ページ専用のマニフェストファイルを作成していきます。なので一般ページはjacascripts/application.js、管理者ページはjavascripts/admin.jsに記載していくことになります。管理者ページではしっかりとjquery3やrails-ujsを指定しないとlink_toのヘルパーメソッドのルーティンでdeleteメソッドを指定出来ないなどの問題が起きてしまいます。

 

app/assets/javascripts/admin.js

//= require jquery3
//= require rails-ujs
//= require admin-lte/plugins/bootstrap/js/bootstrap.bundle.min
//= require admin-lte/dist/js/adminlte

 

このままだと一般ページにもadmin.jsが読み込まれてしまいます。require=treeがjavascriptディレクトリ階層全てのファイルを読み込むので、個別に記載していく必要があります。

 

app/assets/javascripts/application.js

//= require edit_comment

これはコメント編集の時に使ったjsです。require=treeを消して個別に書いていきます。

 

app/assets/stylesheets/admin.scss

@import 'admin-lte/plugins/fontawesome-free/css/all.min.css';
@import 'admin-lte/dist/css/adminlte.css';

ここには、starter.htmlにlinkでここのcssを使用してあると記載してあるので、こちらで専用にimportしてあげる必要があります。

 

マニフェストファイルの読み込み設定

プリコンパイルの設定をします。application以外のマニフェストファイルを個別に読み込みたい場合はプリコンパイルの設定をしないとそのファイルは対象外とされてしまうためエラーが起きてしまいます。

config/initializars/assets.rb

# Be sure to restart your server when you modify this file.

# Version of your assets, change this if you want to expire all your assets.
Rails.application.config.assets.version = '1.0'

# Add additional assets to the asset load path.
# Rails.application.config.assets.paths << Emoji.images_path
# Add Yarn node_modules folder to the asset load path.
Rails.application.config.assets.paths << Rails.root.join('node_modules')
ここでアセットパイプラインのpathの設定が行われている。
# Precompile additional assets.
# application.js, application.css, and all non-JS/CSS in the app/assets
# folder are already added.
Rails.application.config.assets.precompile += %w[admin.js admin.css]
上記がコメントアウトになっているので外してあげる。

 

Userモデルに管理者かどうか判別させるためのroleカラム を追加

$rails g migration AddRoleToUsers role:integer

class AddRoleToUsers < ActiveRecord::Migration[5.2]
  def change
    add_column :users, :role, :integer, default: 0, null: false
  end
end

一般権限となるdefaultは0としてAdmin権限は1とします。

$rails db:migrate

 

enumの追加をする。enumとはモデルの数値カラムに対して文字列の名前を定義することができます。 今回は一般管理者をgeneral、管理者権限をadminとして定義していきます。

user.rb

enum role: { general: 0, admin: 1 }

 

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

$rails g controller admin::base

こうすることでcontorollersの中にadmminディレクトリが作成され、そのなかに新たなコントローラーが作成されます。base_controllerには、application_controller.rbのように、管理者のためのコントローラの基盤となる処理を実装していきます。なので、admin以下のコントローラーは全てbaseコントローラーが継承される記載をしていく必要があります。

admin/base_controller.rb

class Admin::BaseController < ApplicationController
before_action :check_admin
layout 'admin/layouts/application'

private

def not_authenticated
redirect_to admin_login_path, warning: 'ログインしてください'
end

def check_admin
redirect_to root_path, warning: '権限がありません' unless current_user.admin?
end
end

layoutで読み込みたいレイアウトを指定します。この作業はレイアウトは後ほど作成します。 check_adminメソッドでadmin権限でない場合はトップページに遷移させるようにします。

 

$rails g controller admin::dashboards

$rails g controller admin::user_sessions

 

admin/user_sessions_controller.rb

class Admin::UserSessionsController < Admin::BaseController
skip_before_action :require_login, only: %i[new create]
skip_before_action :check_admin, 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

classはbase_contoroller.rbから継承されるように書き直します。ログインのフォーマットは特別にlayoutを変えます。node_modules/admin-lte/dist/pages/examplesにあるlogin.htmlを参考に新たにフォーマットを作成します。

 

admin/dashboards.rb

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

 

 

ルーティングの設定

routes.rb

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

今回は/adminから始まるURLにしたいので、namespaceを使っていきます。これを使うと一般ページと分けて管理することが出来ます。

rootの設定のところでas: :rootを付けないとエラーが出てくるのでつけるようにします。

 

ビューの設定

admin/layoutディレクトリを作成して、その中にapplication.html.erbとadmin_login.html.erbを作成していきます。

 

view/admin/layout/application.html.erb

<!DOCTYPE html>

<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta lang="ja">
<title><%= page_title(yield(:title), admin: true) %></title>
<%= csrf_meta_tags %>
<%# ここでadmin.scssを読み込む %>
<%= stylesheet_link_tag 'admin', media: 'all' %>
</head>

<body class="hold-transition sidebar-mini">
<div class="wrapper">
<%= render 'admin/shared/header' %>
<%= render 'admin/shared/sidebar' %>
<div class="content-wrapper">
<%= render 'shared/flash_message' %>
<%= yield %>
</div>
<%= render 'admin/shared/footer' %>
</div>
<%# admin.jsを読み込む %>
<%= javascript_include_tag 'admin' %>
</body>
</html>

 

view/admin/layout/admin_login.html.erb

<!DOCTYPE html>
<html>
<head>
 <meta charset="utf-8">
 <meta http-equiv="X-UA-Compatible" content="IE=edge">
 <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' %>
</head>

<body class="hold-transition login-page">
 <div>
  <%= render 'shared/flash_message' %>
  <%= yield %>
 </div>
</body>
</html>

 

admin/shared配下にてヘッダー、フッター、サイドバーのパーシャルの作成とログイン画面とトップページの作成をしていきます。(ここは省略)

 

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
end

 

管理者ログイン用のアカウントを作成

User.create!(
 first_name: 'nishiwaki',
 last_name: 'yoshihiro',
 email: 'admin@example.com',
 password: 'password',
 password_confirmation: 'password',
 role: 1
)

 

以上で完成になります。