在Rails中Cookies、Sessions還有Flashes是三種特殊的object,他們使用起來就像是hash一樣。
以下會介紹他們三個在Rails中的使用情境。
Session
在網頁中,由於HTTP是stateless的特性(也就是說server無法在不同的request/response cycle中記住資訊),所以每次request對server來說都是全新的request一樣,server無法得知上個request的狀態。
在實作上,我們會透過在每次client和server間的request加入一個特別的token(也就是session id),讓server知道這些request是來自於哪個使用者、又該紀錄怎樣的狀態。
所以實際上HTTP依舊是statelessness,但是我們透過傳遞session id,讓每次的請求都保持著連線。
舉例來說,當你登入FB後開始瀏覽動態,如果你想針對某個好友的動態點讚,如果沒有任何的東西幫你記憶你目前的狀態,Server會不知道這個request是哪個使用者送出(事實上是你)
在實務上session id常會被存在cookie當中,在每次的request/response中傳遞。
一般來說,每個送到server的request都會經歷以下的過程
- Server檢查request中是否含有session id
- 如果有session id,確認此session id是否有效
- server叫出相對應的資料,並回傳給client端
在Rails中有四種機制來儲存session
- ActionDispatch::Session::CookieStore - Stores everything on the client.
- ActionDispatch::Session::CacheStore - Stores the data in the Rails cache.
- ActionDispatch::Session::ActiveRecordStore - Stores the data in a database using Active Record. (require activerecord-session_store gem).
- ActionDispatch::Session::MemCacheStore - Stores the data in a memcached cluster (this is a legacy implementation; consider using CacheStore instead).
Session除了幫助server記錄狀態外,也可以儲存少量的data。
在Rails中預設使用CookieStore這個選項來儲存session。這個選項最大的不同在於會將所有的session資訊存在cookie當中(經過加密),而不是單純透過存取session id,然後向server取得資料。Server可以直接透過cookie得到session德資料。
以下是在Rails常見的session用法
# Set a session value
session[:current_user_id] = user.id
# Access a session value
some_other_variable_value = session[:other_variable_key]
# Reset a session key
session[:key_to_be_reset] = nil
# Reset the entire session
reset_session
Cookie
我們可以把cookie想像成一個被存在client中的小資料庫,當client端送出請求到server時,會連帶的將這些資料一併傳到server端。而讓server跟client端保持連線的session id,也是被存在cookie中傳送到server端(與將資料存在client端的cookie相對應的,就是將資料存在server端的session)。
像是我們去購物網站購物時,即使我們沒有登入或著註冊該公司的會員身份,仍能夠將商品加入購物車當中。就是因為應用了cookie將資料儲存在瀏覽器上,所以在使用購物網站時,商品才能夠持續顯示在購物車中。
在上面的內容中我們有提到,Rails中是將session hash存在cookie裡。而由於session中常會有很多機密的資訊,所以Rails的使用了ActionDispatch::Cookies::ChainedCookieJars的module
,讓cookie可以被加密,只有server才知道如何解開,避免在clinet端被讀取跟更改。
一般來說我們不會在cookie裡放入太多資料,因為cookie的儲存上限大約4kb。
以下是在Rails常見的cookie用法
# set a cookie value
cookies[:commenter_name] = @comment.author
# Delete cookie for the commenter's name cookie
cookies.delete(:commenter_name)
# Set cookie value with expiration dates
cookies[:name] = { value: "cookies YUM", expires: Time.now + 3600}.
Flash
Flash是session的一部分,而會在下次的request中出現並且被清掉,所以很適合用來顯示提示訊息。
如果你想要讓flash在當前的request就出現,你可以用 flash.now來達成這個目的。
def create
@user = User.new
if @user.save
flash[:success] = "User was created"
redirect_to user_path(@user)
else
flash.now[:error] = "Could not save user"
render action: "new"
end
end
參考資料:
Action Controller Overview
SESSIONS, COOKIES, AND AUTHENTICATION
Class ActionDispatch::Cookies < Object
Module ActionDispatch::Cookies::ChainedCookieJars
Web 技術中的 Session 是什麼?