我一直被教导在会话中存储对象是一个坏主意。而是应存储在需要时检索记录的ID。
但是,我有一个应用程序,我想知道这个规则的例外。我正在构建一个flashcard应用程序,被测试的单词位于数据库的表中,其架构不会更改。我想在会话中存储当前正在进行测验的单词,以便用户可以在他们进入单独页面时完成他们的开始。
在这种情况下,是否可以将这些单词作为对象存储在数据库中?如果是这样,为什么?我问的原因是因为测验的目的是快速移动,而且我讨厌在检索永远不会改变的记录时浪费数据库调用。但是,也许还有一些我不知道的大型会话的负面因素。
*为了记录,我尝试使用Rails 2.3中的内置memcache方法对其进行缓存,但显然每个项目的最大大小为1MB。
答案 0 :(得分:26)
不在会话中存储对象的主要原因是,如果对象结构发生更改,您将获得异常。请考虑以下事项:
class Foo
attr_accessor :bar
end
class Bar
end
foo = Foo.new
foo.bar = Bar.new
put_in_session(foo)
然后,在项目的后续版本中,您更改Bar的名称。您重新启动服务器,并尝试从会话中抓取foo。当它试图反序列化时,它无法找到Bar并爆炸。
看起来似乎很容易避免这个陷阱,但在实践中,我看到它咬了很多人。这只是因为序列化一个对象有时可能会比它更明显(这种事情应该是透明的),除非你有严格的规则,否则事情往往会变得黯然失色。
通常不赞成的原因是,在ActiveRecord中咬人是非常常见的,因为应用程序的结构随着时间的推移而变化很常见,并且会话可以在最初一周或更长时间后反序列化创建
如果您了解所有这些并且愿意投入精力以确保您的模型不会改变并且没有额外的序列化,那么您可能会很好。但要小心:)
答案 1 :(得分:6)
Rails倾向于鼓励RESTful设计,并且使用会话不是非常RESTful。我可能会制作一个包含大量单词的Quiz资源,以及一个current_word。这样,当他们回来时,你会知道他们在哪里。
现在,REST并非一切(取决于你与谁交谈),但是对于大型会话来说这是一个相当不错的案例。请记住,会话在磁盘上写入内容,并且您正在编写的数据越多,回读所需的时间就越长......
答案 2 :(得分:3)
由于您的应用是Rails应用,我建议:
答案 3 :(得分:3)
您在会话中直接存储对象时遇到的一个更加隐蔽的问题是当您使用CookieStore时(我相信Rails 2+中的默认值)。很容易得到很难恢复的CookieOverflow错误。