使用 session


在Rails中如果想要進行高階的會話管理,可以使用session方法,這會傳回Rack::Session::Abstract::SessionHash實例,其父類別為Hash,如果想要在瀏覽器與Web應用程式的會話期間,保留請求之間的相關訊息,則可以使用session方法傳回的方法設定鍵/值。例如:

session[:user] = "caterpillar"

在會話期間,你就可以當作Web應用程式「記得」客戶端的資訊,如果想取出這些資訊,則透過session方法傳回的實例指定鍵取回值。完全可以從高階觀點來進行會話管理,忽略HTTP無狀態的事實。例如:

user = session[:user]


以下的範例是將 隱藏欄位 線上問卷,從隱藏欄位方式改用session方式來實作會話管理:

  • questionaire.html.erb
<%= form_tag "questionaire" do %>
    <% if params[:page] == "Page1" %>
        <%= label_tag "q1", "Question 1: " %><%= text_field_tag "a1" %><br>
        <%= label_tag "q2", "Question 2: " %><%= text_field_tag "a2" %><br>
        <%= submit_tag "Page2", :name => "page" %>
    <% elsif params[:page] == "Page2" 
           session[:a1] = params[:a1]
           session[:a2] = params[:a2] %>
        <%= label_tag "q3", "Question 3: " %><%= text_field_tag "a3" %><br>
        <%= submit_tag "Finish", :name => "page" %>
    <% elsif params[:page] == "Finish" %>
        * A1: <%= session[:a1] %><br>
        * A2: <%= session[:a2] %><br>
        * A3: <%= params[:a3] %>
    <% end %>
<% end %>

程式改寫時,分別利用session來設置第一頁的問卷答案與取得第一頁的問卷答案。你不用考慮HTTP無狀態特性,而親自動手對瀏覽器發送隱藏欄位的HTML。

使用session方法設定的資料,預設有效期限是在關閉瀏覽器前。如果要移除session中某個資料,可以如下:

session[:user] = nil

如果想要在此次會話期間,直接讓目前session設定的資料全部失效,則可以執行ApplicationController的reset_session方法,這會建立新的Rack::Session::Abstract::SessionHash實例,原有的Rack::Session::Abstract::SessionHash實例資料就不見了

一個使用的時機就是實作登出機制,如以下的範例所示範的:

  • tests_controller.rb
class TestsController < ApplicationController
def login if params[:user] == "caterpillar" && params[:passwd] == "123456" session[:user] = params[:user] render "user" end end def user if not session[:user] redirect_to :action => "login" end end

def logout reset_session redirect_to :action => "login" end
end

在登入時,如果名稱與密碼正確,就在session傳回物件中設定一個:user屬性,用以代表使用者作完成登入的動作,其它頁面或動作中如果可以從session取得:user屬性,基本上可代表已登入的使用者,這類用來辨識使用者是否登入的屬性,通常稱之為登入字符(Login Token)。

上面這個範例在登入成功之後,會轉發至使用者頁面:

  • user.html.erb
Welcome! <%= session[:user] %>!<br>
<%= link_to "Logout", :action => "logout" %>

如果有瀏覽器請求使用者頁面,程式會先嘗試取得session的:user屬性,如果無法取得,表示使用者尚未登入,要求瀏覽器重新導向至登入表單。如果可以取得:user屬性,則顯示使用者頁面,頁面中有一個可以執行登出的URL超鏈結,按下後logout動作。

登入的表單如下:

  • login.html..erb
<%= form_tag "login" do %>
    <%= label_tag "user", "User: " %><%= text_field_tag "user" %><br>
    <%= label_tag "passwd", "Password: " %><%= password_field_tag "passwd" %><br>
    <%= submit_tag "Login" %>
<% end %>