2023.10.07 学習記録
昨日の続きから。
- enum
- AdminTEQ
- dartsass
- ルーティングのnamespace
enumはユーザーのroleにgeneralかadminかで設定する感じだなたぶん。
AdminTEQはRUNTEQ独自の管理画面ライブラリで、ビューの下地として使ってねということかと。
dartsassはこれから確認。
DartSass自体はSassの実行環境の一つらしい。
指定のdartsassファイルを作成しadmin配下のscssをプリコンパイルできるようにせよ、とのことなので、アセットパイプライン関連ぽい。以前調べたマニフェストファイルというやつか?
いや、ちょっと違うっぽいな。そもそもrubyファイルだしな…。
このページが参考になりそう。
SassコンパイラとしてDartSassを使うのでその設定ファイルを作ってね、その中でadmin配下のscssをプリコンパイルできるように設定を書いてね、ということだと今はざっくり認識しておく。
次。ルーティングのnamespaceについて。
名前空間という概念がいまいちピンときてないんだよなあ…
まずはRailsガイド。
あーなるほどグループ化機能みたいなものなのか、名前空間。少なくともコントローラについて言えば。コントローラをネストできるみたいな。
ルーティングでコントローラの名前空間使うのとリソースをネストする違いは、「コントローラ自体がネストしてるかどうか」かな?
よし、大体の把握はできた。初見時に思ったほど複雑ではなさそうだ。
タスクの洗い出しをするために、実際の操作を順番に追ってみる。
- 管理者ログイン画面にアクセス
- メールアドレスとパスワードでログイン
- 管理画面トップページ(ダッシュボード)が表示される
大雑把にやるべきことを書き出す。
- 管理者ログイン画面にアクセス
- ルーティングの設定
- コントローラの作成
- ビューの作成
- メールアドレスとパスワードでログイン
- userモデルにroleカラムを追加
- ログイン周りのロジックを実装
- 管理画面トップページ(ダッシュボード)が表示される
- ビューの作成
タスク
- ルーティングの設定
- コントローラの作成
-
ビューの作成
- AdminTEQを導入
- 管理者ログイン画面
- 管理画面トップページ
-
userモデルにroleカラムを追加
- マイグレーション
- バリデーション設定
- ログイン周りのロジックを実装
ログインロジックの分解とかdartsassの設定とかはやりながら考えることにてしてとりあえず始動!
まずはルーティング。namespaceを使ってネストしたadmin関連のコントローラを使えるようにする。
…と思ったけどよく課題の仕様みたらコントローラに関する指定が何もないな。これだと今回の内容だけならわざわざ「/controllers/admin」てしなくても良さそうだけど、ポイントにnamespaceを使ったルーティングが入っているってことは、たぶん次の課題で必要になるからそうしたほうがいいんだろうな。そうする。
とりあえず/controllers/adminにuser_sessionsコントローラを作ることにしてルーティング追加した。
お、いい情報載ってた。...と思ったけど再度見直したらやっぱり課題詳細内にコントローラに関する記述あった!なんとなく見た覚えはあるけどないなと思ったら単に見落としだった…。
application_controllerを継承したadmin/base_controllerを作って、更にそのadmin/base_controllerを継承元にしていろんなadmin系コントローラを作ればいいんだな。てことは
namespace :admin do
:base, :user_sessions
end
でいいのかなとりあえず。やってみよう。
user_sessionsコントローラは一部のアクションしかいらないんだけど、onlyオプションとか使えるのかな。
resourcesが抜けてた😞こう↓か。
namespace :admin do
resources :base
resource :user_session, only %i[ new create destroy ]
end
ちゃう!こうか
namespace :admin do
get 'login', to: 'user_sessions#new'
post 'login', to: 'user_sessions#create'
delete 'logout', to: 'user_sessions#destroy'
end
管理画面トップページはURLが「/admin」になるようにとのことだけど、adminの名前スペースの中でrootに設定するとかでいけるんだろうか?とりあえずやってみる。
コンソールで確かめたところOKの模様。次はコントローラの生成。
…の前に。
せっかく課題用のリポジトリを自分のGitHub上にも作ったんだからここでissue利用して実装タスク管理するのがいいんじゃないかと気づいた。
やってみるか。
初めてissueを作ってみた。とりあえずこれで進めよう。
気を取り直してコントローラの生成。/controllers/admin下にbase_controllerとuser_sessions_controllerを生成する。
namespaceを使用して生成することもやはりできる模様。
baseコントローラが無事できた。ディレクトリのネストもバッチリ。user_sessionsコントローラはどうしよう。rails g
だとapplication_controllerを継承しちゃうんだよなあ。回避方法あるんだろうか。
ぱっと出てこないな。まあいいや、rails g
してから継承元を手動で書き換えよう。
生成OK。継承元も書き換えた。
次はuserモデルにroleカラムを追加する。まずはマイグレーションファイルを生成。
null: false
以外になにか必要な制約あるかな…とりあえず思いつかないのでこのままマイグレーション実行する。,
OK。
ここでnull: false
にした以上既存のユーザーにもroleを付与しないとな気づいたので、seedsを編集して対応することにする。
seedsを書いていて更に気づいたが、先にenumの宣言をしたほうがいいかも?そっちからやるか。
と思ってenumの使い方について改めて調べたら、若干自分の理解と違う?ひょっとしたらカラムの追加やり直しかも。もうちょい調べてみる。
うーんRailsガイドに載ってるやり方と検索して出てくる記事に載ってるやり方が違うなあ。記事だと各値を整数もしくは真偽値に紐付けてるけど、Railsガイドではそのまま指定してる。どっちが主流なんだ?
あ、なるほど。こっち↓を読んだらちょっとわかった。
Railsガイドのやり方は各値に対応する整数の表記を省略してる(というかハッシュではなく配列を使って表記している?)だけなんだ。結局実態は整数であって、それを文字列で表現できるようにしてあるっていうところは同じ。# これと、
class Task < ApplicationRecord
enum status: { todo: 0, in_progress: 1, done: 2 }
end
# これは同じ
class Task < ApplicationRecord
enum :status, [ :todo, :in_progress, :done ]
end
てことはやっぱりカラムの追加やり直しだな。ロールバック!
データ型をintegerに変更、更にdefaultを0にして再度マイグレーション。
OK。改めてenum宣言する。
OK。seedsも改めて修正。
seedsを更新したのでdb:reset
を実行。
無事新しいユーザーデータが生成された。
モデル周りの準備ができたので、ビューの作成に入る。
まずはAdminTEQのインストール。指定のコマンドをコンテナ内で実行。
OK。ログインページのファイルを作成(とりあえず作るだけ、中身はあと)
管理画面トップページはどこに配置するべきなんだろう?もう一回ヒント見てみるか。
そっかまずはレイアウトファイルを通常用とは別に作らなきゃだ。/layoutの中に/adminを作るべきか?
あとヒントの中の記述を見た感じ、トップページはbaseじゃなくて別のコントローラ(dashboards)作るべきっぽいな。base_controllerはapplication_controllerのadmin版ってイメージかな。
というわけでdashboardsコントローラを生成して、ルーティングを修正する。
OK。
ビューのディレクトリ構成については、/layouts下にadmin.html.erbというレイアウトファイルをとりあえず作ってみる。
ここまでやって思ったけど、application.html.erb以外のレイアウトファイルを呼び出す方法が必要だな。調べる。
いちおうrender
メソッドのlayoutオプションで使うレンダリングに使うレイアウトファイルを指定できるらしい。
メソッド単位じゃなくもうちょっと広く適用できないかな。
あった。コントローラ単位でできるから、/admin/base_controllerに設定すればadmin関連全部に適用できるな。
2.2.14.1 コントローラ用のレイアウトを指定する
デフォルトのレイアウト名ルールは、以下のようにlayout宣言で上書きできます。class ProductsController < ApplicationController
layout "inventory"
#...
end
この宣言によって、上のコードのProductsControllerのレンダリングで>app/views/layouts/inventory.html.erb>レイアウトが使われるようになります。アプリケーション全体で特定のレイアウトを使いたい場合は、layoutをApplicationControllerクラスで宣言します。
class ApplicationController < ActionController::Base
layout "main"
#...
end
この宣言によって、アプリケーションのすべてのビューでapp/views/layouts/main.html.erbレイアウトが使われるようになります。
さっそく設定した。ログイン画面の方は完全に独立したオンリーワンのレイアウトだから個別指定にしよう。
管理画面トップページは/view/admin/dashboards下に作ることにする。
AdmimTEQからコピペしたコードを貼り付けたので、とりあえず管理画面トップページにアクセスしてみる。
レイアウト指定のコードで表記ミスをしていてエラー、修正。
dashboardsコントローラにindexアクションを定義し忘れてエラー、修正。
で、次はこれが出た
TypeError at /admin
superclass mismatch for class DashboardsController
dashboardsコントローラのクラス名が「DashboardsController」になっていた。「Admin::DashboardsController」に修正。
通常のログイン画面に飛ばされて「ログインしてください」というフラッシュメッセージが出た。そりゃそうだ。application_controllerを継承してるんだからそうなるわな。
とりあえず確認のためskip_before_actionする。
内容はともかく表示はされた。というかこれ、ログイン画面用だった、間違えた。ログイン画面の方に移植する。
ついでにログイン画面の方もskip_before_actionしてアクセスできるか確認する。
OK。両方問題なく表示された。レイアウトの使い分けもできている。
あ、render
メソッドにオプションとして指定する場合はビューファイル名は省略してOKみたい。
修正。
ログインフォーム含めログイン周りのロジックを作っていく。
まずはコールバックの設定。
- baseコントローラに
require_login
をroleがadminのユーザーのみという条件を加えてオーバーライドして定義 - user_sessionsコントローラのnewとcreateアクションは
skip_before_action
↑はちょっと違うか。require_login
はオーバーライドせずそのまま残して、新たに管理者権限があるユーザーが確認するメソッドを定義しよう。
admin_user?
メソッドを定義してbaseコントローラにbefore_action
として設定した。
次はログインフォームの作成。
見た目はともかくログインフォームはできた。
休憩を挟んでTILを作成・プッシュしたら今日はおしまい。
明日はuser_sessionsコントローラのcreateアクションを作るところから始める。