Kaz Chocomint's

シドニーで生活しながら考えたこと、勉強していることについてまとめていくブログ

Ruby on Rails チュートリアルをやってみる 第九章

年明け、1日から2日まで二日間かかって終わらせることができました。難易度としては、量の多い8章の方が高いように感じました。残念ながらここでもテストの項目で一件調べても解決できない課題が残ってしまいました。この一件も本筋のコードに大きな影響がなさそうなのでとりあえずおいて次の章に進むことにします。残り3章、一ヶ月以内という目標は達成できそうですが、思った以上に後半がきつく、内容の完全な理解のために何回かじっくりと読み直す必要がありそうです。

⭐️未解決解決:9.56: 管理者権限の制御をアクションレベルでテストするとerrorになる
エラーコード

ERROR["test_should_redirect_destroy_when_not_logged_in", UsersControllerTest, 1.3612923190084985]
 test_should_redirect_destroy_when_not_logged_in#UsersControllerTest (1.36s)
NoMethodError:         NoMethodError: undefined method `admin?' for nil:NilClass
            app/controllers/users_controller.rb:74:in `admin_user'
            test/controllers/users_controller_test.rb:48:in `block (2 levels) in <class:UsersControllerTest>'
            test/controllers/users_controller_test.rb:47:in `block in <class:UsersControllerTest>'
current_user.admin



2016/1/13 追記
10章を終えた段階でもう一度、このエラーについて調べてみました。
before actionの、ログイン済ユーザー(logged_in_user)に対して許可するアクションについてdestroyを入れ忘れていたのが原因でした。

ファイル場所→app/controllers/users_controller.rb内で、以下のとおりlogged_in_userにdestroyアクションが許可されていませんでした。

 class UsersController < ApplicationController
  before_action :logged_in_user, only: [:index, :edit, :update ]
  before_action :admin_user,     only: :destroy
  .
  .
end

今回errorのtestでは、ログインしない状態でdestroy(削除)アクションを実行するが、対象のuserが消えずにlogin_urlにリダイレクトされてたら成功というものです。

  test "should redirect destroy when not logged in" do
    assert_no_difference 'User.count' do
      delete :destroy, id: @user
    end
    assert_redirected_to login_url
  end

before actionのlogged_in_userにないため、destroyアクションをトリガーとしてlogged_in_userの処理が実行されず、login_urlにリダイレクトできません。それだとfailになるはず、、、と思ったのですが、destoryはadmin_userに対してはbefore_actionにてdestroyを許可しているために、admin_userは実行されて、current_user.adminと書かれているように、current_userでもないのでテストが例外処理によりerrorになったと理解しました。…勉強になりました。失敗から学ぶことは多いですね。
それでも失敗は辛いですが。。。

    #beforeフィルター
    #ログイン済みユーザーかどうか確認
    def logged_in_user
      unless logged_in?
        store_location
        flash[:danger] = "Please log in."
        redirect_to login_url
      end
    end 
    # 管理者かどうか確認
    def admin_user
      redirect_to(root_url) unless current_user.admin?
    end