[分享] 如何解決教材中「訪客以網址進入 admin/jobs 出現錯誤」

狀況描述

照著招聘網站教材完整作完,有一個小彩蛋(bug):「未登入的訪客,如果想要以網址進入查看後台的列表,出現錯誤訊息:NoMethodError in Admin::JobsController#index」,假如已經上傳到 Heroku,則會看到:"We're sorry, but something went wrong."

你可以參考此張動圖試試看:在未登入的情況下,利用網址列:localhost:3000/admin/jobs 嘗試進入後台的工作列表。

錯誤原因

之所以會有這個 bug,我們可以先來看一下 admin 相關的代碼找原因:

  1. app/controllers/admin/jobs_controller.rb

在使用者作任何 admin/jobs_controller.rb 定義的任何動作之前,都要先過 before_action :require_is_admin 這關,也就是,使用者必須要是 admin。

  1. app/controllers/application_controller.rb

在 application_controller.rb,def require_is_admin 中的 if 判斷式判斷的是 if !current_user.admin?,也就是判斷:「當前已登入的使用者(current_user)」是不是 admin。

​ 這樣我們就找到問題在哪了!未登入的使用者,並不適用於 current_user.admin? 這個判斷。要排除這個小問題,以下提供兩種解決方案。

解決方案一:

代碼:

app/controllers/application_controller.rb

if 判斷式改成:if !current_user || !current_user.admin?
如此一來 def require_is_admin 會判斷:

  • 「未登入的使用者( !current_user )」
  • 「登入,但非管理員的使用者( !current_user_admin )」

只要滿足任一條件,就會擋住使用者。

class ApplicationController < ActionController::Base
    def require_is_admin
      if !current_user || !current_user.admin? #多加一個 OR 判斷條件「未登入的使用者」

        flash[:alert] = "You are not an admin."
        redirect_to jobs_path
      end
    end
end

結果:

使用者在未登入的狀況下嘗試進入 http://localhost:3000/admin/jobs,會看到 "You are not an admin.",並被導回首頁的工作列表。

解決方案二:

代碼:

app/controllers/admin/jobs_controller.rb

修改 before_action :authenticate_user!,在檢查 require_is_admin 之前,我們就先確認使用者是否有登入。這個解決方案背後的邏輯是:如果沒有登入的話,自然不可能是 admin 管理員。

class Admin::JobsController < ApplicationController
  before_action :authenticate_user! #改成這樣,表示在所有動作之前,都要檢查使用者的登入狀態。

  before_action :require_is_admin

結果:

修改後,admin/jobs_controller 在使用 before_action require_is_admin 檢查權限之前,會先判斷使用者有沒有登入。所以,使用者在未登入的狀況下嘗試進入 http://localhost:3000/admin/jobs ,會看到 "You need to sign in or sign up before continuing." 並被導到登入介面。

Comments

comments powered by Disqus