Logging out
現在要來實作使用者登出。也就是要透過 Sessions controller 的 destroy action 來銷毀 session。
之前的登入功能 log_in 我們在兩個地方:app/controllers/users_controller.rb、app/controllers/sessions_controller.rb 都有用到,不過登出的話只需要放在一個地方就好,也就是直接在 destroy action 處理就可以了。
登出其實就是要解除 log_in 的操作,也就是從 session 中刪除使用者的 ID,所以使用 delete 方法:
session.delete(:user_id)
同時也把目前使用者設為 nil,不過其實在這種情況下有沒有這個步驟都沒差別,因為登出後會導向首頁(root_path),和 log_in 一樣,把 log_out 方法放在 Sessions 輔助方法裡:
app/helpers/sessions_helper.rb
module SessionsHelper
# Logs in the given user.
def log_in(user)
session[:user_id] = user.id
end
.
.
.
# Logs out the current user.
def log_out
session.delete(:user_id)
@current_user = nil
end
end
然後再把 log_out 輔助方法放進 destroy action 裡面:
app/controllers/sessions_controller.rb
def destroy
log_out
redirect_to root_url
end
然後可以在 test/integration/users_login_test.rb 增加測試登出的功能:
test/integration/users_login_test.rb
test "login with valid information followed by logout" do
get login_path
post login_path, 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
登入後,使用 delete 向 logout_path 發出 DELETE 請求,然後確認使用者已經登出,重新導向到 root_path,還要確認出現 login_path 連結,logout_path、profile 連結都消失。
現在可以在測試中使用 is_logged_in?,所以向 login_path 發送有效資訊之後,我們增加了 assert is_logged_in?。
執行測試應該會通過(Green):
$ bundle exec rake test