Ruby-on-rails 在 Rails 的会话中存储对象
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1095714/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Storing Objects in a Session in Rails
提问by Yehuda Katz
I have always been taught that storing objects in a session was a bad idea. Instead IDs should be stored that retrieve the record when needed.
我一直被教导在会话中存储对象是一个坏主意。相反,应该存储 ID,以便在需要时检索记录。
However, I have an application that I wonder is an exception to this rule. I'm building a flashcard application, and the words being quizzed are in a table in the database whose schema doesn't change. I want to store the words currently being quizzed in a session, so a user can finish where they started in case they move on to a separate page.
但是,我有一个应用程序,我想知道它是此规则的一个例外。我正在构建一个抽认卡应用程序,被测验的单词位于数据库中的一个表中,其架构不会改变。我想在会话中存储当前正在测验的单词,以便用户可以在他们开始的地方完成,以防他们转到单独的页面。
In this case, is it possible to get away with storing these words as objects in the database? If so, why? The reason I ask is because the quiz is designed to move quickly, and I'd hate to waste a database call on retrieving a record that never changes in the first place. However, perhaps there are other negatives to a large session that I'm not aware of.
在这种情况下,是否可以将这些单词作为对象存储在数据库中?如果是这样,为什么?我问的原因是因为测验旨在快速进行,而且我不想浪费一次数据库调用来检索从不改变的记录。但是,也许我不知道大型会议还有其他负面影响。
*For the record, I have tried caching it with the built-in memcache methods in Rails 2.3, but apparently that has a maximum size per item of 1MB.
*作为记录,我尝试使用 Rails 2.3 中的内置 memcache 方法缓存它,但显然每个项目的最大大小为 1MB。
回答by Yehuda Katz
The main reason not to store objects in the session is that if the object structure changes, you will get an exception. Consider the following:
不在会话中存储对象的主要原因是,如果对象结构发生变化,则会出现异常。考虑以下:
class Foo
attr_accessor :bar
end
class Bar
end
foo = Foo.new
foo.bar = Bar.new
put_in_session(foo)
Then, in a subsequent release of the project, you change Bar's name. You reboot the server, and try to grab foo out of the session. When it tries to deserialize, it fails to find Bar and explodes.
然后,在项目的后续版本中,您更改 Bar 的名称。您重新启动服务器,并尝试从会话中获取 foo。当它尝试反序列化时,它找不到 Bar 并爆炸。
It might seem like it would be easy to avoid this pitfall, but in practice, I've seen it bite a number of people. This is just because serializing an object can sometimes take more along with it than is immediately apparent (this sort of thing is supposed to be transparent) and unless you have rigorous rules about this, things will tend to get flummoxed up.
避免这个陷阱似乎很容易,但在实践中,我已经看到它咬了很多人。这只是因为序列化一个对象有时会带来比显而易见的更多的东西(这种事情应该是透明的),除非你对此有严格的规则,否则事情往往会变得混乱。
The reason it's normally frowned upon is that it's extremely common for this to bite people in ActiveRecord, since it's quite common for the structure of your app to shift over time, and sessions can be deserialized a week or longer after they were originally created.
它通常不受欢迎的原因是它在 ActiveRecord 中咬人是非常常见的,因为你的应用程序的结构随着时间的推移而改变是很常见的,并且会话可以在最初创建后一周或更长时间反序列化。
If you understand all that and are willing to put in the energy to be sure that your model does not change and is not serializing anything extra, you're probably fine. But be careful :)
如果您了解所有这些并且愿意投入精力确保您的模型不会改变并且不会序列化任何额外的东西,那么您可能没问题。不过要小心 :)
回答by Steve Klabnik
Rails tends to encourage RESTful design, and using sessions isn't very RESTful. I'd probably make a Quiz resource that has a bunch of words, as well as a current_word. This way, when they come back, you'll know where they were.
Rails 倾向于鼓励 RESTful 设计,而使用 session 并不是很 RESTful。我可能会制作一个包含一堆单词和 current_word 的测验资源。这样,当他们回来时,你就会知道他们在哪里。
Now, REST isn't everything (depending on who you talk to), but there's a pretty good case against large sessions. Remember that sessions write things to and from disk, and the more data that you're writing, the longer it takes to read back...
现在,REST 并不是万能的(取决于您与谁交谈),但是对于大型会话有一个很好的案例。请记住,会话向磁盘写入内容和从磁盘写入内容,并且您写入的数据越多,回读所需的时间就越长......
回答by Steve Klabnik
Since your app is a Rails app, I would suggest either:
由于您的应用程序是 Rails 应用程序,因此我建议:
- Using your clients' ability to cache by caching the cards in javascript. (you'd need a fairly ajaxy app to do this, see the latest RailsCastfor some interesting points on javascript page caching)
- Use one of the many other rails-supported server-side caching options (i.e. MemCached) to cache this data.
- 通过在 javascript 中缓存卡片来使用客户端的缓存能力。(您需要一个相当 ajaxy 的应用程序来执行此操作,有关 javascript 页面缓存的一些有趣点,请参阅最新的RailsCast)
- 使用许多其他支持 rails 的服务器端缓存选项(即 MemCached)之一来缓存此数据。
回答by Julian H
A much more insidious issue you'll encounter storing objects directly in the session is when you're using CookieStore (the default in Rails 2+ I believe). It's very easy to get CookieOverflow errors which are very hard to recover from.
当您使用 CookieStore(我相信 Rails 2+ 中的默认设置)时,您会遇到直接在会话中存储对象的一个更隐蔽的问题。很容易出现 CookieOverflow 错误,而这些错误很难恢复。

