8.3 ログアウト
ここでは、ログアウト機能を追加する
ログアウト用リンクは既に作成済みなので、ユーザーセッションを破棄するための有効なアクションをコントローラで作成するだけで済む。これまでSessionsコントローラのアクションはRESTfulルールに従っていた。newでログインページを表示し、createでログインを完了、といった具合。
セッションを破棄するdestroyアクションも、同じ要領で作成する。ただし、ログインの場合とは異なり、ログアウト処理は1ヶ所で行えるので、destroyアクションに直接ログアウト処理をかくことにする。具体的には、log_inメソッドの実行結果を取り消す。つまり、セッションからユーザーIDを削除する。
session.delete(:user_id) ←①
①:sessionはハッシュのようであった。ハッシュにおいて、引数に指定したキーに対応する値をハッシュ自身から取り除くには、例えば
h = {"japan" => "yen", "US" => "dollar"} h.delete("japan")
とすればよい。これと同じ考え方。
app/helpers/sessions_helper.rb
# 渡されたユーザーでログインする def log_in(user) session[:user_id] = user.id end # 現在の ユーザーをログアウトする def log_out ←追加 session.delete(:user_id) @current_user = nil end
ここで定義したlog_outメソッドは、Sessionsコントローラのdestroyアクションでも同様に使う。
controllers/sessions_controller.rb
def destroy log_out redirect_to root_url end
ユーザーログアウトのテスト
test/integration/users_login_test.rb
test "login with valid information followed by logout" do get login_path post login_path, params: { session: { email: @user.email, password: 'password' } } assert is_logged_in? ←追加 assert_redirected_to @user follow_redirect! assert_template 'users/show' assert_select 'a[href=?]', login_path, count: 0 assert_select 'a[href=?]', logout_path assert_select 'a[href=?]', user_path(@user) #ログアウト(ココから追加) delete logout_path ←① assert_not is_logged_in? ←② assert_redirected_to root_url ←③ follow_redirect! ←④ assert_select "a[href=?]", login_path ←⑤ assert_select "a[href=?]", logout_path, count: 0 ←⑥ assert_select "a[href=?]", user_path(@user), count: 0 end
①:ユーザーがログアウトして、ログアウトリンクが消えたらtrue
②:テストユーザーがログイン中でなければ(つまりログアウトなら)true
③:homeにリダイレクトされていればtrue
④:リダイレクト先(root_url)が正しいかチェック
⑤:login_path(/login)がhref=/loginというコードで存在していればtrue
⑥:href="/logout"が存在しなければ(0なら)true