说我想在控制器中存储一些变量。我想在一个动作中初始化它,在另一个动作中增加它,然后在另一个动作中读取它。仅使用@foo
声明此变量不起作用,因为@foo
在创建创建它的操作后死亡。
我不希望将此变量存储在模型中。
除了将它存储在会话中之外,还有办法保留这个变量吗? 好像我已经遇到过这个简单的问题了几次,我想知道解决问题的最佳方法。
答案 0 :(得分:22)
不是真的。每次调用控制器操作都是无状态的。控制器操作完成后,没有任何内容可用。为每个请求创建一个新的控制器实例,然后在请求结束时将其丢弃。
如果您不想将其存储在会话或数据库模型中,那么如果您希望该变量特定于特定会话,则没有很多选项。
如果它在所有会话中都是全局的,您可以将它放在@@class_variable
而不是@instance_variable
中,但是一旦开始有多个Rails进程(每个进程都有自己的进程),这可能会变得混乱它的副本),或者如果你在线程安全模式下运行,你最终可能会遇到令人讨厌的并发错误。
我猜你可以看看像memcached这样的东西,但你仍然需要将其键入某个user_id或其他会话标记(除非它是全局的)
答案 1 :(得分:11)
我也想知道为什么你反对使用会话?如果您不喜欢直接在您的操作中使用会话,则可以使用过滤器模拟幸存的@foo
实例变量。这样的事可能吗?
class FooController < ApplicationController
before_filter :load_foo
after_filter :save_foo
private
def load_foo
@foo = session[:foo] || 0
end
def save_foo
session[:foo] = @foo
end
end
您的操作将能够通过@count
实例变量操纵值,并且会自动持久保存到会话。
答案 2 :(得分:7)
您可以使用内置的Rails.cache机制来存储值,但正如第一个答案中所提到的,您必须将其键入user_id之类的内容。这是一个很好的方法,因为你可以使用不同的存储机制来支持它。
Rails.cache.write(:foo)
# in later action
Rails.cache.read(:foo)
另一件你可以看到的是flash hash,它提供了一个keep方法来使flash值持续多个后续请求。
因此,在操作1中,您可以创建值:
flash[:foo] = some_value
flash.keep(:foo)
在操作2中,您可以访问它,如果您希望它保持活动状态以便进行更多后续操作,请再次调用keep。
flash[:foo] #use it for something
flash.keep(:foo) # keep it for another request
在http请求的上下文中干净地完成这件事有点棘手。
答案 3 :(得分:1)
如果它是一个简单的计数或字符串,我认为最好的解决方案是将它存储在会话中。这样,如果您使用多个Web服务器,它就会存在。
你为什么不反对使用会话?
答案 4 :(得分:1)
别担心,会议不会咬人。
此外,会话可能是最好的方法。