学びシリーズ第3弾です。
作ってみた機能
RailsのSession有無判定による画面制御の実装
環境構成
全体構成・完成イメージ
[DB]TABLE
なし
プログラムコード等
Controller
■ application_controller.rb
class ApplicationController < ActionController::Base class Forbidden < StandardError; end ・・・ 1 rescue_from Forbidden, with: :rescue_403 ・・・ 2 private def current_manager ・・・4 # 遅延初期化ロジックに書き換え # Manager.find_by(id: session[:manager_id]) if session[:manager_id] if session[:manager_id] # @current_memberオブジェクトが存在しない場合のみ実行 @current_manager ||= Manager.find_by(id: session[:manager_id]) end end helper_method :current_manager def login_required ・・・ 3 raise Forbidden unless current_manager end def rescue_403(exception) ・・・ 2 render "errors/forbidden", status: 403, layout: "error", formats: [:html] end end
- Forbiddenクラスを作成し、StandardErrorクラスに継承させます。
- rescue_fromメソッドを使って、エラーハンドリングできるようにします。上記の場合、Forbiddenエラーが発生した時にrescue_403メソッドを呼ぶようにしています。rescue_403メソッドでは、Forbiddenエラーが起きた時にエラー用のViewを呼び出す様に記載しています。viewsディレクトリ配下にerrorsフォルダを作成し、forbidden.html.erbを作成します。あとはエラーなので、statusに403を設定。error用のlayoutを使用。jpg等の拡張子付きのパスを入力されてもhtmlでエラー画面を表示する様にformatsオプションを設定します。
- Sessionを持たない場合に、Forbiddenエラーが発生させるメソッドを作成します。あとは、Controllerに「before_action :login_required」と記載するだけで、このメソッドを呼ぶ事ができます。
- 学びシリーズ第二弾で作成したcurrent_managerメソッドも少し改良を加えて、遅延初期化ロジックに書き換えています。遅延初期化とは、事前にオブジェクトや変数に値を設定しておくのではなく、オブジェクトや変数に値が設定されていない(存在しない)時にだけ値を設定することを言います。Rubyプログラマはこういった遅延初期化ロジックを好む人が多いみたいです。でも、たしかに無駄の無いロジックですし右辺の実行回数も減るのでこちらの方がスッキリしますね。
以下、ご参考です。
ERB
■ error.html.erb(layout)
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> <%= @page_title %> </title> </head> <body> <%= link_to "戻る", :root %> <%= yield %> </body> </html>
■ forbidden.html.erb
<% @page_title = "Forbidden" %> <h1>403 Forbidden</h1> <p>このページにはアクセスできません。</p>
学んだ事
Session有無判定によって画面の表示/非表示を切り替える機能は、セキュリティ的に大変重要な機能の1つだと思うのですが、Railsだと以外と簡単に実装できる事に驚きました。Session有無が判定できる事で、ログインしていないと見せられない画面や機能や表示もコントロールできるので、できる事の幅が大きく広がった気がします。また、遅延初期化というのも初めて知りました。こちらも大変勉強になりました。