在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 %>