【Rails6】Devise + Bootstrapで管理画面用認証機能を作る

【Rails6】Devise + Bootstrapで管理画面用認証機能を作る

今回は、ユーザ認証用のGEMであるDeviseと簡単なデザインを施すためのBootstrap4をrails6に適用して、WEBアプリケーション用の管理画面を作るための下ごしらえをしていきます。
なお、本記事では管理画面用のGEMは利用していません。

実現したい機能は以下の通りです。

  • 管理者用ユーザーの作成
  • 管理者用ユーザーの編集
  • 管理者用ユーザーの削除
  • 管理者用ユーザーのログイン/ログアウト
  • 管理者ユーザーのパスワード再設定

動作環境

macOS Catalina 10.15.4
ruby 2.7.1
Rails 6.0.2.2

Railsプロジェクトの作成

2020年5月時点で最新版を導入します。

rails new devise-sample

ルートページを追加します。

rails generate controller home index

確認用にconfig/routes.rbにを以下を追記します。

root to: 'home#index'

rails serverを実行し、動作することを確認します。

Bootstrapの導入

次にBootstrapの導入を行います。
font-awesomeも追加したいので以下のように入力。

yarn add bootstrap jquery popper.js @fortawesome/fontawesome-free

bootstrapとfont-awesomeのJS部分をインクルードするため、以下を’app/javascript/packs/application.js’に追加します。

require("bootstrap");
require("@fortawesome/fontawesome-free");

続いて、bootstrapとfont-awesomeのCSS部分をインクルードします。
application.cssをapplication.scssに変更し、以下を記述。ついでにログイン画面用スタイルも追加

/*
 *= require_tree .
 *= require_self
 */

$fa-font-path: '@fortawesome/fontawesome-free/webfonts';
@import '@fortawesome/fontawesome-free/scss/fontawesome';
@import '@fortawesome/fontawesome-free/scss/regular';
@import '@fortawesome/fontawesome-free/scss/solid';
@import '@fortawesome/fontawesome-free/scss/brands';
@import 'bootstrap/scss/bootstrap';

// Devise用

.container-login {
  @extend .container-fluid;
  max-width: 576px;
  padding: 2rem;
}

.alert-notice {
  @extend .alert-info;
}

.alert-alert {
  @extend .alert-danger;
}

Home#indexのViewの内容を書き換えて、bootstrapとfont-awesomeの動作を確認します。

<h1>Home#index</h1>
<p>Find me in app/views/home/index.html.erb</p>
<a href="#" class="btn btn-primary">Hello <i class="fas fa-cat"></i></a>



ついでに多くのpackでjQueryを使うことを想定して、config/webpack/environment.jsに以下を仕込んでおきます。

const { environment } = require('@rails/webpacker')
var webpack = require('webpack');

environment.plugins.append(
  'Provide',
  new webpack.ProvidePlugin({
    $: 'jquery',
  })
)

module.exports = environment

Deviseの導入

まずはGEMのインストールからです。
Gemfileに以下を追加

gem 'devise'
gem 'devise-bootstrap-views', '~> 1.0'
bundle install

deviseをインストールします。

rails g devise:install

config/environments/development.rbに以下を追記。

config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }

config/initializers/devise.rbのScopes configurationを変更

  # ==> Scopes configuration
  # Turn scoped views on. Before rendering "sessions/new", it will first check for
  # "users/sessions/new". It's turned off by default because it's slower if you
  # are using only default views.
  config.scoped_views = true

Deviseのカスタマイズ

今回は、管理者用ユーザーのモデルを作りたいので以下のようにモデルを生成。(そのうちWEBサービスを利用するユーザー側の認証を別途追加する想定)

rails g devise admin

標準の機能で十分なのでそのままDBに反映します。

rails db:create db:migrate

admin用コントローラーを追加します。

rails g devise:controllers admins

次にviewを整えていきます。
app/views/layouts/application.html.erbにレスポンシブ対応のためのmetaタグとDevise関連のページやflashを表示するパーシャルを追加をします。

<!DOCTYPE html>
<html>
  <head>
    <title>DeviseSample</title>
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
    <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
  </head>

  <body>
    <%= render 'shared/header' %>
    <%= render 'shared/flash_messages' %>
    <%= yield %>
  </body>
</html>

app/views/shared/_flash_messages.html.erb

<% flash.each do |msg_type, msg| %>
  <div class="alert alert-<%= msg_type %>" role="alert" id="alert">
    <a href="#" class="close" data-dismiss="alert">×</a>
    <%= msg %>
  </div>
<% end %>

app/views/shared/_header.html.erb

<header>
  <nav class="navbar navbar-expand navbar-light">
    <%= link_to "サンプル", root_path, class: 'navbar-brand' %>
    <div id="Navber">
      <ul class="navbar-nav">
        <% if admin_signed_in? %>
          <li class="nav-item active">
            <%= link_to '編集', edit_admin_registration_path, class: 'nav-link' %>
          </li>
          <li class="nav-item active">
            <%= link_to 'ログアウト', destroy_admin_session_path, method: :delete, class: 'nav-link' %>
          </li>
      <% else %>
          <li class="nav-item active">
            <%= link_to "新規登録", new_admin_registration_path, class: 'nav-link' %>
          </li>
          <li class="nav-item active">
            <%= link_to "ログイン", new_admin_session_path, class: 'nav-link' %>
          </li>
        <% end %>
      </ul>
    </div>
  </nav>
</header>

rails サーバーを再起動して、適切に表示されているか確認します。



最後に、管理画面用ダッシュボードを作成して、ログインしないとアクセスできないようにしてみます。

rails g controller admin::dashboard index

作成されたコントローラに記述します。
app/controllers/admin/dashboard_controller.rb

class Admin::DashboardController < ApplicationController
  before_action :authenticate_admin!

  def index
  end
end

ログインしたら、作成したダッシュボードに飛ぶように変更します。
app/controllers/application_controller.rb

class ApplicationController < ActionController::Base
  def after_sign_in_path_for(resource)
    admin_dashboard_index_path
  end
end

実際に画面で操作すると、正しくログインできることが確認できました。

またログインしていない状態で’/admin/dashboard/index’にアクセスするとエラーメッセージが正常に表示されました。


■ログイン後


■未ログインでアクセス

今回はここまでにします。
管理者用ユーザーモデルを実装したので、実際にWEBサービスを使うユーザー用のモデルも別途作成でき応用が効くと思います。