Say I want to store some variable in my controller. I want to initialize it in one action, increment it in another, and read it in yet another. Just declaring this variable with @foo
doesn't work because @foo
dies after the action that created it is rendered.
I do not want this variable to be stored in a model.
Is there a way to preserve this variable besides storing it in a session?
It seems like I've run into this simple problem a few times, and I want to know the best way to go about solving it.
I too am wondering why you are against using session? If you don't like working with session directly in your actions, you could emulate a surviving @foo
instance variable with filters. Something like this maybe?
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
Your actions will the be able to manipulate the value through the @count
instance variable and this will be automatically persisted to session.
Not really. Each call to a controller action is stateless. Nothing is available after the controller action finishes. A new controller instance is created for each request, and then discarded at the end of the request.
If you don't want to store it in the session, or database model, you don't have many options if you're wanting that variable to be specific to a particular session.
If it is global across all sessions, you could put it in a @@class_variable
rather than an @instance_variable
, but that can get messy once you start having multiple Rails processes (each which will have their own copy of it), or if you're running in threadsafe mode, you can end up with nasty concurrency bugs.
I guess you could look at something like memcached, but you'd still need to key that to some user_id or other session marker (unless it's global)
You could make use of the built in Rails.cache mechanism to store the value but as mentioned in the first answer you'd have to key it off something like the user_id. This is a nice way to go since you can back it with different storage mechanisms.
Rails.cache.write(:foo)
# in later action
Rails.cache.read(:foo)
One other thing you could look at is the flash hash, which provides a keep method to make the flash value last more than one subsequent request.
So in action 1 you could create the value:
flash[:foo] = some_value
flash.keep(:foo)
In action 2 you can access it, and call keep again if you want it to stay alive for more subsequent actions.
flash[:foo] #use it for something
flash.keep(:foo) # keep it for another request
It's a bit of a tricky thing to do cleanly within the context of http requests.
If it's a simple count or string, I think the best solution is to store it in the session. That way it will be there if you are using multiple web servers.
Why are you against using a session for this?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With