LoginSignup
3
2

More than 1 year has passed since last update.

Rails 管理者画面作成 AdminLTE 解説

Last updated at Posted at 2022-01-21

AdminLTE 3 のインストール

ターミナル
yarn add admin-lte@^3.0

・node_modulesというディレクトリが作成される。

管理者画面用のマニフェストファイルの設定

・管理者画面ではユーザー画面とレイアウトが全く別物の為、管理者画面とユーザー画面は分ける。
・「app/assets/javascripts/admin.js」「app/assets/stylesheets/admin.scss」ファイルを作成。

app/assets/javascripts/application.js
//= require jquery3
//= require activestorage
//= require rails-ujs
//= require bootstrap-sprockets
//= require cable.js
//= require tree. ←ここを削除

//= require tree.はapplication.jsと同じ階層の全ファイルを読み込んでいる。今回作成した、admin.jsも同じ階層にあるので、それぞれのファイルにあるrails-ujsやjquery3が同時に読み込まれると二重になりエラーが起きる。

別々にファイルを読み込むように設定

・それぞれのファイルに以下のように記述

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
app/assets/stylesheets/admin.scss
@import 'admin-lte/plugins/fontawesome-free/css/all.min.css';
@import 'admin-lte/dist/css/adminlte.css';

config/initializer/assets.rbの修正

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
migrationファイル_add_role_to_users.rb
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を使って定義する。

app/models/user.rb
enum role: { general: 0, admin: 1 } #追加

・roleカラムに0が保存されていればgeneral,1が保存されていればadminという定数で扱うということになる。*後でroleを追加した際に数字を明示していないと、「"general"=>0, "admin"=>1」のように必ず紐ずくという状態にならない。

・enumを使うと、カラム(ここではrole)に指定した定数が入っているレコードを取り出すのが容易になる。

・現ユーザーがadmin(管理者)かどうかを判断したいときにcurrent_user.admin?というものが使えるようになる。

ルーティングの設定

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を使うことによって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

管理者画面のレイアウトを設定

controllers/base_controller.rb
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を継承させていく。

app/controllers/admin/dashboards_controller.rb
class Admin::DashboardsController < Admin::BaseController #ここを変更
  def index; end
end

admin/base_controller.rbを継承しているので、layout 'admin/layouts/application'と記述しなくてもよい。

app/controllers/admin/user_sessions_controller.rb
class Admin::UserSessionsController < Admin::BaseController #ここを変更

end

管理者ユーザーレイアウト(テンプレート)

app/views/admin/layouts/application.html.erb
<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

app/views/admin/dashboards/index.html.erb
<% content_for(:title, t('.title')) %> 
<div class="content-wrapper">
  <div class="row">
   <p>ダッシュボードです</p>
  </div>
</div>

タイトルを設定

app/helpers/application_helper.rb
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)を表示。

管理者用共通レイアウトに読み込む

app/views/admin/layouts/application.html.erb
<title><%= page_title(yield(:title), admin: true) %></title> 

yield(:title)個別レイアウト(各view)のタイトル

個別レイアウト(各view)に読み込む

<% content_for(:title, t('.title')) %>  #titleは翻訳ファイルに記入

content_for個別レイアウトから共通レイアウトに表示する時に使用

コントローラー

・作成したbase_controllerに追記していく

app/controllers/base_controller.rb
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_useradminかを判定している。
・enumでroleカラムの整数をadminと定義したので、admin?が使用できる。
application_controllerbefore_action :require_loginを記述しているので、ログインしていない場合は自動的にnot_authenticaedというメソッドを実行。(Sorceryのヘルパー)
・ログインしていなければ、管理者用のログインページへリダイレクトさせる。

管理者用ログイン画面のコントローラーを作成

ターミナル
$ rails g controller Admin::User_sessions new
app/controllers/admin/user_sesssion_controller.rb
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メソッド)で検証を行なっている)

ルーティング

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

ログイン用のレイアウトのテンプレート

app/views/layouts/admin_login.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' %>
</head>
<body class="hold-transition login-page">
  <div>
    <%= render 'shared/flash_message' %>
    <%= yield %>
  </div>
</body>
</html>
app/views/admin/user_sessions/new.html.erb
<% 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>

管理者ユーザーを作成

db/seeds.rb
User.create!(last_name:  "aa",
             first_name: "aa",
             email: "a@a.com",
             password:  "aaa",
             password_confirmation: "aaa",
             role: 1)

role: 1roleカラムを1にしてadmin(管理者)に設定

ターミナル
$ rails db:seed

rails db:seedコマンドでコマンドを実行するとDBに反映される。

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2