“会话”session

Rails 的“会话”是个类似哈希表的结构,它在请求期间会一直有效。不像原始的cookie,
“会话”可以持有任何对象(只要这些对象可以被marshale),来保存web 应用程序内的状态信息。例如,在我们的store 应用程序中,我们使用了一个“会话”在请求之间持有购物车对象。此购物车对象在我们的应用程序中使用起来应该像其它对象一样。但是Rails 安排在每个请求处理的尾部保存购物车,更重要的是,在Rails 启动来处理一个引入的请求时,适当的购物车会被重新存储。使用会话,我可以让我们应用程序逗留在请求之间。

此处有两个部分。首先,Rails 必须保持“会话”的引用。它通过创建(缺省地)一个32hex
的字符key 键来做此事。这个key 键被称为“会话”id,并且它是随机数。Rails 在用户的浏览器上安排存储这个“会话”id 为一个cookie(带有key_session_id)。随后来自于这个浏览器的对应用程序的请求,Rails 可以重新获得“会话”id。
Rails 在服务端保持一个持久的“会话”数据仓库,可通过“会话”id 来索引。这有两
个“会话”魔术。当一个请求到达时,Rails 使用“会话”id 来查看数据仓库。它会发现此数据是个序列化的Ruby 对象。它反序列化此数据并将结果存储在“控制器”的session 属性中。此处数据对我们应用程序代码是有效的。应用程序可以添加或修改这个数据的内容。当它完成对每个请求的处理后,Rails 把“会话”数据写回到数据仓库中。并在那里等待这个浏览器的随后请求。
我们应该在“会话”内存储什么呢?你需要的任何东西,只要遵循少数的约束和警告。

[align=center][color=red]session对象存储内容的限制[/color][/align]
1、在一个“会话”中对你能存储一些种类的对象有约束。细节依赖于你所选择的存储机
制。(稍后我们就会看到)在通常情况下,“会话”内对象必须是被序列化的(使用Ruby 的“重组”(Marshal)功能)。例如,这意味着你不能在“会话”中存储I/O 对象。

2、如果你在“会话”中存储任何Rails“模型”,你将必须添加“模型”的声明给它们。
这会让Rails 预先加载“模型”类,以便它的定义在Ruby 反序列化“会话”仓库时是有效的。如果“会话”被限制为只用于一个“控制器”,则它的声明可放在那个“控制器”的顶部。
class BlogController < ApplicationController
model :user_preferences
# . . .
可是,如果较多的model类对象要声明,这时可以直接声明给app/controllers 目录下全局的application_controller.rb 文件。

3、不要在“会话”数据中存储大的对象—而把它们放到数据库内,并从“会话”
中引用它们。

4、不要在session对象中存储易失性数据,你或许不想在“会话”数据内存储valatile(暂态)对象。例如,你可能想保持博客内一定数量的文章,并且出于性能的原因把它们存储在“会话”中。但是,如果你这样做的话,在其它用户添加了新文章的话,计数不会得到更新。
将表现当前登录用户的对象存储在“会话”中是很诱人。但是如果你的应用程序可以由
非法用户使用,这就可能不是你希望的了。即使数据库内的用户无效,它们的“会话”数据
将仍有有效状态。在数据库内存储volatile(暂态)数据并从“会话”中引用它。

5、你或许不想在“会话”数据中存储重要信息。例如,如果你的应用程序在一个请求中
产生一个定单信息号,并且存储它在“会话”数据中以便于在处理下个请求时将它存回到数
据库中。如果用户从它的浏览器中删除了cookie,你就要冒丢失号码的危险。重要信息应该
保存在数据库中。这是个很大的漏洞。如果你在“会话”数据中存储一个对象,然后下一次你从你的应用程序的浏览器中重新取回那个对象。但是,如果在此期间你更新了你的应用程序,那么“会话”数据内的对象可能就会与你的应用程序内该对象的类的定义不一致。

则应用程序在处理这个请求时会失败。此处有三种选择。
一是使用常规的“模型”存储对象在数据库中,并只在“会话”中保持行的id 字段。“模型”对象对Ruby 的Marshal 库的改变是最宽容的。

第二种选择是在你修改用于存储数据的类的定义时,在你的服务端手工删除所有的“会话”数据。

第三种选择稍微有些复杂。如果你给你的“会话”的key 键添加一个版本号的话,那么
你更新被存储的数据时会修改版本号,你将只加载与应用程序的当前版本号相应的数据。你
可以为存储在“会话”内的对象使用潜在的版本,并依赖与每次请求关联的“会话”key 键
来使用适当的类。最后的选择需要大量的工作,所以你将需要决定它是否值得。

因为“会话”以类似哈希表的形式被存储,所以你可以在其中保存多个对象,每个都带
有它自己的key 键。下面代码中,我们存储登录用户的id 在“会话”中。并在后面创建的
index“动作”中使用它。
为用户定制个菜单。我们也记录最后被选择的菜单条目的id,并在index 页面中使用id
来选择。当我们使用日志时,我们会重置所有“会话”数据。
class SessionController < ApplicationController
def login
user = User.find_by_name_and_password(params[:user],
params[:password])
if user
session[:user_id] = user.id
redirect_to :action => "index"
else
reset_session
flash[:note] = "Invalid user name/password"
end
end
def index
@menu = create_menu_for(session[:user_id])
@menu.highlight(session[:last_selection])
end
def select_item
@item = Item.find(params[:id])
session[:last_selection] = params[:id]
end
def logout
reset_session
end
end

像通常的Rails 习惯,缺省的“会话”很方便,但如果需要我们可以覆写它。这种情况
下,“会话”的选项是全局的,所以你典型地会在你的环境文件中
(config/environment.rb或config/environments 目录下的一个文件)设置它们。[此处有个例外—你不能以这种方式设置“会话”失效时间。]这不是API 式的设置选项:你只是简单地直接设置值到DEFAULT_SESSION_OPTIONS 哈希表中。例如,如果你想修改你应用程序使用的cookie 的名字,
你会在环境文件中添加下面东西。
ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS
[:session_key] = 'my_app'

有效的“会话”选项是:
1、:database_manager 控制“会话”数据如何被存储到服务端。
2、:session_domain 用于在浏览器上存储“会话”id 的cookie 域。缺省是应用程序的
主机名字。
3、:session_id 覆写缺省的“会话”id。如果没有设置,新的“会话”将自动具有32
位的key 键。此key 键被用于随后的请求中。
4、:session_key 用于存储“会话”id 的cookie 的名字。你将在你的应用程序中覆写
它,就像前面显示的。
5、:session_path 应用于这个“会话”的请求路径。缺省值是“/”,所以它应用于这
个区域内的所有应用程序。
6、:session_secure 如果设置的话,“会话”将只对https://有效。缺省值为false。
7、:new_session 直接映射底层的cookie 的new_session 操作。但是,这个选项在Rails
下不会像你想像那样工作,我们在323 页16.8 节讨论另一个选择。
8、:session_expires 此“会话”失效的绝对时间。像:new_session,这个选项或许不
应该在Rails 下使用。
另外,你可以指定依赖于存储类型的选项。例如,如果你选择使用Pstore 数据管理“会
话”数据,你可以控制Rails 存储文件的位置,以及预先确定各个文件的名字。
class DaveController < ApplicationController
session_options
= ::ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS
session_options[:tmpdir] = "/Users/dave/tmp"
session_options[:prefix] = "myapp_session_"
# ...
这些细节可查看CGI::Session 的标准Ruby 文
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值