在Rails中的会话中存储对象

我一直被教导在会话中存储对象是一个坏主意。 而是应该存储ID,以便在需要时检索记录。

但是,我有一个应用程序,我想知道这个规则的例外。 我正在构建一个flashcard应用程序,被测试的单词位于数据库的表中,其架构不会更改。 我想在会话中存储当前正在进行测验的单词,因此用户可以在他们进入单独页面的情况下完成他们开始的位置。

在这种情况下,是否可以将这些单词作为对象存储在数据库中? 如果是这样,为什么? 我问的原因是因为测验旨在快速移动,而且我讨厌在检索永远不会改变的记录时浪费数据库调用。 但是,也许还有一些我不知道的大型会话的负面影响。

*为了记录,我尝试使用Rails 2.3中的内置memcache方法缓存它,但显然每个项目的最大大小为1MB。

不在会话中存储对象的主要原因是,如果对象结构发生更改,则会出现exception。 考虑以下:

class Foo attr_accessor :bar end class Bar end foo = Foo.new foo.bar = Bar.new put_in_session(foo) 

然后,在项目的后续版本中,您更改Bar的名称。 您重新启动服务器,并尝试从会话中抓取foo。 当它试图反序列化时,它无法找到Bar并爆炸。

看起来似乎很容易避免这个陷阱,但在实践中,我看到它咬了很多人。 这只是因为序列化一个对象有时可以更多地使用它而不是立即明显(这种事情应该是透明的)除非你有严格的规则,否则事情往往会变得黯然失色。

它通常不赞成的原因是,在ActiveRecord中咬人是非常常见的,因为应用程序的结构随着时间的推移而变化很常见,并且会话可以在最初创建后一周或更长时间内反序列化。

如果您了解所有这些并且愿意投入精力以确保您的模型不会发生变化并且没有额外的序列化,那么您可能会很好。 不过要小心 :)

Rails倾向于鼓励RESTful设计,并且使用会话不是非常RESTful。 我可能会制作一个包含大量单词的Quiz资源,以及一个current_word。 这样,当他们回来时,你会知道他们在哪里。

现在,REST不是一切(取决于你与谁交谈),但是对于大型会话来说这是一个非常好的案例。 请记住,会话在磁盘上写入内容,并且您正在编写的数据越多,回读所需的时间就越长……

由于您的应用是Rails应用,我建议:

  1. 通过在javascript中缓存卡片,使用客户端缓存的能力。 (你需要一个相当ajaxy的应用程序来做到这一点,请参阅最新的RailsCast ,了解javascript页面缓存的一些有趣点)
  2. 使用许多其他rails支持的服务器端缓存选项之一(即MemCached)来缓存此数据。

你会遇到直接在会话中存储对象的一个​​更加阴险的问题是当你使用CookieStore时(我相信Rails 2+中的默认值)。 很容易得到很难恢复的CookieOverflow错误。