#AdminLTE 3 のインストール
yarn add admin-lte@^3.0
・node_modulesというディレクトリが作成される。
#管理者画面用のマニフェストファイルの設定
・管理者画面ではユーザー画面とレイアウトが全く別物の為、管理者画面とユーザー画面は分ける。
・「app/assets/javascripts/admin.js」「app/assets/stylesheets/admin.scss」ファイルを作成。
//= require jquery3
//= require activestorage
//= require rails-ujs
//= require bootstrap-sprockets
//= require cable.js
//= require tree. ←ここを削除
・//= require tree.
はapplication.jsと同じ階層の全ファイルを読み込んでいる。今回作成した、admin.jsも同じ階層にあるので、それぞれのファイルにあるrails-ujsやjquery3が同時に読み込まれると二重になりエラーが起きる。
###別々にファイルを読み込むように設定
・それぞれのファイルに以下のように記述
//= require jquery3
//= require rails-ujs
//= require admin-lte/plugins/bootstrap/js/bootstrap.bundle.min
//= require admin-lte/dist/js/adminlte
@import 'admin-lte/plugins/fontawesome-free/css/all.min.css';
@import 'admin-lte/dist/css/adminlte.css';
#config/initializer/assets.rbの修正
Rails.application.config.assets.precompile += %w[admin.js admin.css] ←この部分をコメントアウト
・admin.js admin.cssをプリコンパイルしている。
#一般ユーザーと管理者ユーザーを分ける
###Adminのコントローラーを作成
$ rails g controller Admin::Base
・adminディレクトリ階層を作成する理由は、レイアウトファイルなど、通常の一般ユーザー画面と別物にしたいのでこのadmin/base_controller.rb
をベースに作成していく。
$ rails g controller Admin::Dashboards index
rails g controller Admin::User_sessions new
###UserモデルにAdminを判別するカラムを追加
$ rails g migration add_role_to_users
class AddRoleToUsers < ActiveRecord::Migration[5.2]
def change
add_column :users, :role, :integer, null: false, default: 0
end
end
・roleというカラムでデータ型はstring(整数)、空は許可しない(null: false),初期値には0(default:0)を指定。
・一般ユーザーと管理者ユーザーを判断する為にroleカラムを追加。(整数:stringで管理する)
・integer型は整数を保存する型で2個以上の定数と紐づけることができる。
$ rails db:migrate
###一般ユーザーを「0」、管理者ユーザーを「1」をenumを使って定義する。
enum role: { general: 0, admin: 1 } #追加
・roleカラムに0
が保存されていればgeneral
,1
が保存されていればadmin
という定数で扱うということになる。*後でroleを追加した際に数字を明示していないと、「"general"=>0, "admin"=>1」のように必ず紐ずくという状態にならない。
・enumを使うと、カラム(ここではrole)に指定した定数が入っているレコードを取り出すのが容易になる。
・現ユーザーがadmin(管理者)かどうかを判断したいときにcurrent_user.admin?
というものが使えるようになる。
###ルーティングの設定
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
を使うことによってURLとファイル構成を指定のパス(admin)にすることができる。(以下のようになる)
admin_root GET /admin(.:format) admin/dashboards#index
admin_login GET /admin/login(.:format) admin/user_sessions#new
POST /admin/login(.:format) admin/user_sessions#create
admin_logout DELETE /admin/logout(.:format) admin/user_sessions#destroy
#管理者画面のレイアウトを設定
class Admin::BaseController < ApplicationController
layout 'admin/layouts/application' #layoutを宣言
end
・現状のままでは、ApplicationController
を継承しているので、レイアウト(共通するファイル)はviews/layouts/application.html.erb
になっている。
・layout
を宣言する事でadmin/layouts/application
を設定する事ができる。
・先程作成した、ダッシュボード用コントローラ(admin/dashboards_controller.rb)
とログイン用のコントローラー(admin/user_sessions_controller.rb)
にadmin/base_controller.rb
を継承させていく。
class Admin::DashboardsController < Admin::BaseController ←#ここを変更
def index; end
end
・admin/base_controller.rb
を継承しているので、layout 'admin/layouts/application'
と記述しなくてもよい。
class Admin::UserSessionsController < Admin::BaseController ←#ここを変更
end
###管理者ユーザーレイアウト(テンプレート)
<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' %>
<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' %>
<div class="content-wrapper">
<%= render 'shared/flash_message' %>
<%= yield %>
</div>
<%= render 'admin/shared/footer' %>
</div>
<%= javascript_include_tag 'admin' %>
</body>
</html>
#ダッシュボード用のview
<% content_for(:title, t('.title')) %>
<div class="content-wrapper">
<div class="row">
<p>ダッシュボードです</p>
</div>
</div>
#タイトルを設定
module ApplicationHelper
def page_title(page_title = '', admin = false)
base_title = if admin
'学習用掲示板(管理画面)'
else
'学習用掲示板'
end
page_title.empty? ? base_title : page_title + ' | ' + base_title
end
・「各ビューのタイトル | 固定タイトル」
のような形でタイトルを設定していく。
・viewと別の場所(helper)で定義しておくとviewから呼び出すことができる。
・メソッドの引数を柔軟に変えられるデフォルト値付き引数である(page_title = '')
を使って、引数あり・なしで表示を変えている。
・empty?
メソッドは、タイトルが空の場合タイトルに固定タイトル(base_title)
を表示。タイトルがあれば、各ビューのタイトル | 固定タイトル(base_title)
を表示。
###管理者用共通レイアウトに読み込む
<title><%= page_title(yield(:title), admin: true) %></title>
・yield(:title)
個別レイアウト(各view)のタイトル
###個別レイアウト(各view)に読み込む
<% content_for(:title, t('.title')) %> #titleは翻訳ファイルに記入
・content_for
個別レイアウトから共通レイアウトに表示する時に使用
#コントローラー
・作成したbase_controller
に追記していく
class Admin::BaseController < ApplicationController
before_action :check_admin
layout 'admin/layouts/application'
private
def not_authenticated
flash[:warning] = t('defaults.message.require_login')
redirect_to admin_login_path
end
def check_admin
redirect_to root_path, warning: t('defaults.message.not_authorized') unless current_user.admin?
end
end
・privateに記述したbefore_action :check_admin
でログインしたcurrent_user
がadmin
かを判定している。
・enumでroleカラムの整数をadminと定義したので、admin?
が使用できる。
・application_controller
でbefore_action :require_login
を記述しているので、ログインしていない場合は自動的にnot_authenticaed
というメソッドを実行。(Sorceryのヘルパー)
・ログインしていなければ、管理者用のログインページへリダイレクトさせる。
#管理者用ログイン画面のコントローラーを作成
$ rails g controller Admin::User_sessions new
class Admin::UserSessionsController < Admin::BaseController ←#BaseControllerを継承している
skip_before_action :require_login, only: %i[new create]
skip_before_action :check_admin, only: %i[new create]
layout 'layouts/admin_login'
def new; end
def create
@user = login(params[:email], params[:password])
if @user
redirect_to admin_root_path, success: t('.success')
else
flash.now[:danger] = t('.fail')
render :new
end
end
def destroy
logout
redirect_to admin_login_path, success: t('.success')
end
end
・layout 'layouts/admin_login'
ログインページ用のレイアウトを宣言
・@user = login(params[:email], params[:password])
mailとpasswordが一致していれば@userにデータが代入される(loginメソッド(sorceryメソッド)で検証を行なっている)
###ルーティング
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
#ログイン用のレイアウトのテンプレート
<!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' %>
</head>
<body class="hold-transition login-page">
<div>
<%= render 'shared/flash_message' %>
<%= yield %>
</div>
</body>
</html>
<% content_for(:title, t('.title')) %>
<div class="login-box">
<div class="login-logo">
<h1><%= t('.title') %></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, User.human_attribute_name(:email) %>
<div class="input-group mb-3">
<%= f.text_field :email, class: 'form-control', placeholder: :email %>
<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>
#管理者ユーザーを作成
User.create!(last_name: "aa",
first_name: "aa",
email: "a@a.com",
password: "aaa",
password_confirmation: "aaa",
role: 1)
・role: 1
roleカラムを1にしてadmin(管理者)に設定
$ rails db:seed
・rails db:seed
コマンドでコマンドを実行するとDBに反映される。