管理画面を作りたい(メモ書き)
量が多いのでひとまず細かい手順は記載しません。
課題の反省点
- タスクを上手く分解できなかった
- 何をすべきかは分かっていても、どうすべきなのか検討がつかなかった
大まかな実装の流れ
- yarnでAdminLTE3をインストールする
- コントローラ、ルーティング作成
- admin-lteから使いたいテンプレートをそのままコピペする
- マニフェストファイルに読み込むべきファイルを記載する
- コピペしたテンプレ内に作成したマニフェストファイルを読み込む記載をする
- ビューを分解し、共通レイアウトでレンダリングさせる
- 動的な
<title>
の作成、翻訳追加
ユーザー管理用のコントローラ作成
- application_controllerを継承するadmin/base_controllerを作成
→base_controllerには管理系共通の処理を記載
→Admin::BaseController
という名前をつけることで、Adminというモジュールの名前空間の中にbase_controllerというクラスを定義することになる - Railsではモジュール階層を、コードを保存するためのディレクトリ階層に対応させているため、上記の記述によりapp/controllers/admin/base_controller.rbというファイルが対応することになる
- 管理系の機能を足したいときに、Admin::のついたコントローラを追加していけば、コードがadminディレクトリの下にまとまって分かりやすい
class Admin::BaseController < ApplicationController
↑BaseControllerはApplicationControllerを継承
管理系の各コントローラはこのBaseControllerを継承する設計にする。
作成したいコントローラ
- admin/dashboards_controller.rb(管理画面トップページへ)
- admin/user_sessions_controller(管理者ログインフォーム)
- 管理者用ログイン画面の立ち位置について
→管理者用のログイン画面なだけであってまだこの時点では管理画面ではない(ログイン状態にない)という解釈からビューをviews/layouts配下に置くか、管理画面に関する画面と解釈し、views/admin/layouts配下に置くのか、解釈によって分ける
管理用コントローラとルーティング
2.6 コントローラの名前空間とルーティング | Railsガイド
コントローラは名前空間でグループ化することができる。
管理系のコントローラはAdmin::名前空間の中に作成しているため、ルーティングはこの名前空間でグループ化することができる。
以下のようにnamescpaceブロックを使ってグループ化する
namespace :admin do resources :articles, :comments end
- 管理画面は
/admin
のみでアクセスできるようにroot to:
を使用 - user_sessionsは一般ユーザーのルーティングを参考に以下の通り
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
rails consoleで仮の権限持ちユーザーを作っておく
seedsファイルを使った作成方法にまだ行きついていないので仮に作っておく
User.create!(first_name: "admin", last_name: "admin", email: "admin@example.com", password: "password", password_confirmation: "password", role: 1 )
これでログインできるか確かめる
AdminLTEのインストール、マニフェストファイルについて
マニフェストファイルに読み込み設定
アセットパイプラインに「node_modules」のpathが通っているの確認
% rails c > Rails.application.config.assets.paths
↓なんかモリモリ出てきた😨
#<Pathname:/Users/user_name/workspace/***/rails_2/5***/node_modules>
とりあえずこんな表示が入っていればパスが通っているらしい。
パスが通っていない場合はconfig/initializers/assets.rb
に下記パスを記載
↑自分のは元々記載されていた。
管理者判定用のroleカラム(enum型)をusersテーブルに追加する
Usersテーブルにroleカラムをenum(列挙)型で追加する
enum型とは?
一つのカラムに指定した複数個の定数を保存できるようにするためのもの。
今回の例で言えば、role(役割)というカラムにgeneral(一般)とadmin(管理者)という二つの定数を保存したい。
特徴
- 指定した複数個の定数以外は保存できなくなる
- カラムに指定した定数が入っているレコードを取り出すのが容易になる
- enumはinteger型(0,1,2...)、もしくはboolean型(true,flase)としてDBに保存される
enumを使うためには?
①テーブルにenum用カラムを追加
bundle exec rails g migration AddRoleToUsers
② changeメソッドを編集
class AddRoleToUsers < ActiveRecord::Migration[5.2] def change add_column :users, :role, :integer, default: 0, null: false # 必ず一般ユーザーか権限ユーザーに振り分けるのでNOTNULL制約を追加 # generalは0、adminは1が入るようにuser.rbに後ほど記載 end end
③ enumのカラムに複数個の定数を紐づけていく
# user.rb enum role: { general: 0, admin: 1 } # 定数の数が多い場合、配列(シンボルor文字列)で書くとスッキリする # 配列で定義するとインデックスが自動で定数と紐づいてくれる enum role: [ :general, :admin ] enum role: [ "general", "admin" ]
※注意点
- enumを使うならboolean型はあまり使わない方が良い。
- enumの魅力は複数の定数を定義できること、そもそもtrueかfalseの二択で良いのなら、booleanだけで十分。enumを使う必要はない。
- Rails5.2系でfalseにupdateする際にnullに更新しようとするバグが発生している。
エラー
admin_login.html.erbに<%= csrf_meta_tags %>
の記述がないの下記エラーが発生するらしい。
ただ自分は<%= csrf_meta_tags %>
を追加してもエラーが解決しなかった。Ajaxで送信するフォームだと<%= csrf_meta_tags %>
を<head>
内で呼び、X_CSRF_Tokenをリクエストヘッダーに付与することでCSRF対策ができるそうな。
RailsのPOSTでCSRF TokenがVerifyできないときに確認したいこと - Qiita
formはlocal: trueのまま変更していないから、タグを追加しても変わらなかったのか🤔??
class ApplicationController < ActionController::Base protect_from_forgery # 追加
↑の記載を追加することでエラーが解決 【Rails API】ActionController::InvalidAuthenticityTokenの解決方法 - Qiita
このあとbase_controllerに記載したcheck_adminの判定ロジックにおいてnilに対して呼び出しているエラーが出たため、ぼっち演算子に変更したところ問題なく動作した。
参考にしたサイト
enum
【Rails】 enumチュートリアル | Pikawaka
AdminLTE
[管理画面]Rails 5 に yarnでインストールした「AdminLTE3.0.0-alpha.2」 を適用させる方法 - Qiita
AdminLTEを使って管理者用機能を実装する(トップページ) - Programming Learning Diary
AdminLTE 3を使って管理者ページを実装しよう - プログラミングの備忘録
CSRF(クロスサイトリクエストフォージェリー)対策
ActionController::InvalidAuthenticityTokenの解消(解決済み) - Blogメモφ(..)
ActionController::InvalidAuthenticityTokenのエラーが出る|simesime|note
【Rails API】ActionController::InvalidAuthenticityTokenの解決方法 - Qiita