# Using SessionTimeout: which actions need session data?

**URL:** <https://www.ruby-forum.com/t/using-sessiontimeout-which-actions-need-session-data/86494>\
**Category:** Rails\
**Created:** [February 22, 2007, 6:45pm UTC](https://www.ruby-forum.com/t/using-sessiontimeout-which-actions-need-session-data/86494 "2007-02-22T18:45:08Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![weyus](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/w/7ab992/32.png) [@weyus](https://www.ruby-forum.com/u/weyus)\
**Post date:** [February 22, 2007, 6:45pm UTC](https://www.ruby-forum.com/t/using-sessiontimeout-which-actions-need-session-data/86494/1 "2007-02-22T18:45:08Z")

</div>

All,

I’ve successfully implemented SessionTimeout. It works great.

On a given request, assuming that the session has timed out, what I’d  
like to do is have my session timeout handler be smart enough to  
determine which actions in my app. actually require session data in  
order to function correctly vs. actions which don’t require session  
data.

Then the handler can redirect to the original requested action IF it  
DOESN’T require the use of session data. IF the original requested  
action DOES require the use of pre-existing session data, then the  
handler would redirect to some predefined “restarting” action.

Obviously, I know my app. and I can specify which actions are in which  
camp via hard coding etc. Not a problem. However, it would be nice to  
be able to determine this in some more generic way. The most generic  
rule for figuring out the disposition of a given action would seem to  
be:

IF the contents of an action contain any assignment statement (or return  
value) that includes a reference to a session hash member (e.g. x =  
session[:blah]), then this action requires pre-existing session data and  
cannot be safely redirected to after a session timeout. Otherwise, (no  
assignment or return statements that reference a session hash member),  
the action is safe to be redirected to after a session timeout.

Can anyone think of a clever way to encapsulate a generic test for this?

If a fully generic test can’t be created, one way to handle this could  
be to maintain lists of “safe-to-redirect-to” vs.  
“unsafe-to-redirect-to” methods in each controller and then just  
interrogate the controllers to figure it out in the session timeout  
handler.

Thanks,  
Wes

---

<div class="post-metadata">

**Author:** ![weyus](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/w/7ab992/32.png) [@weyus](https://www.ruby-forum.com/u/weyus)\
**Post date:** [February 22, 2007, 7:31pm UTC](https://www.ruby-forum.com/t/using-sessiontimeout-which-actions-need-session-data/86494/2 "2007-02-22T19:31:33Z")

</div>

I would handle this using two separate before\_filter actions. For  
example,

before\_filter expire\_session  
before\_filter authenticate

expire\_session - if expired reset\_session  
authenticate - check session for some defined value (e.g.  
session[:user]) and  
act depending on whether value is initialized.

For controllers that don’t require session, don’t add the filter. For  
actions  
that don’t require session, use except =\> [:action1, :action2, …]  
along with  
the filter.

I am not sure you will gain anything trying to detect whether an action  
requires  
session or not, besides complexity.

HTH,

– Long  
[http://MeandmyCity.com/](http://MeandmyCity.com/) - Free online business directory for local  
communities  
[http://edgesoft.ca/blog/read/2](http://edgesoft.ca/blog/read/2) - No-Cookie Session Support plugin for  
Rails

---

<div class="post-metadata">

**Author:** ![weyus](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/w/7ab992/32.png) [@weyus](https://www.ruby-forum.com/u/weyus)\
**Post date:** [February 22, 2007, 9:19pm UTC](https://www.ruby-forum.com/t/using-sessiontimeout-which-actions-need-session-data/86494/3 "2007-02-22T21:19:29Z")

</div>

Long,

Thanks, but that isn’t quite what I want. I want the session to expire  
after a specific time between consecutive requests, regardless of which  
action is requested. Your proposal would seem to tie session expiry to  
a particular set of actions.

Wes

---

<div class="post-metadata">

**Author:** ![weyus](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/w/7ab992/32.png) [@weyus](https://www.ruby-forum.com/u/weyus)\
**Post date:** [February 22, 2007, 10:42pm UTC](https://www.ruby-forum.com/t/using-sessiontimeout-which-actions-need-session-data/86494/4 "2007-02-22T22:42:56Z")

</div>

Perhaps I misunderstood your question.

A session expires after a period of inactivity. The next request will  
kick  
start the expiring process in the expire\_session filter. I believe this  
action  
should just perform house cleaning, reset\_session and return true  
(always).

The authenticate filter runs next. It may check like

if !session[:user] then  
redirect\_to ‘login’  
return false  
end

Note here the before filters will run before control is passed to the  
requested action, whatever that may be. Though, you can control  
which action the filters will affect by using either except =\> [] or  
only =\> [] options.

I hope I am talking about the same thing you are. If not sorry I can’t  
help.

Cheers,

– Long

----- Original Message -----  
From: “Wes G.”

---

<div class="post-metadata">

**Author:** ![weyus](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/w/7ab992/32.png) [@weyus](https://www.ruby-forum.com/u/weyus)\
**Post date:** [February 22, 2007, 11:47pm UTC](https://www.ruby-forum.com/t/using-sessiontimeout-which-actions-need-session-data/86494/5 "2007-02-22T23:47:46Z")

</div>

Long wrote:

> Perhaps I misunderstood your question.
> 
> A session expires after a period of inactivity. The next request will  
> kick  
> start the expiring process in the expire\_session filter. I believe this  
> action  
> should just perform house cleaning, reset\_session and return true  
> (always).
> 
> The authenticate filter runs next. It may check like
> 
> if !session[:user] then  
> redirect\_to ‘login’  
> return false  
> end

Long,

I understand all of that.

I’d like to point out that in my case, my session timeout callback  
method attempts to redirect\_to somewhere no matter what. I have to  
always return _false_ from it because everything I have is protected by  
my authenticate filter. Since I would have a new session (created by  
session\_timeout) and no session[:user], I would get a double  
render/redirect error if the session timeout callback returned true and  
allowed the authenticate filter to run.

My question was about making an intelligent decision about which action  
to redirect\_to _within_ the session timeout callback.

Wes

---

<div class="post-metadata">

**Author:** ![weyus](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/w/7ab992/32.png) [@weyus](https://www.ruby-forum.com/u/weyus)\
**Post date:** [February 23, 2007, 12:41am UTC](https://www.ruby-forum.com/t/using-sessiontimeout-which-actions-need-session-data/86494/6 "2007-02-23T00:41:10Z")

</div>

Wes G. wrote:

> Long,
> 
> I understand all of that.

Alright.

> I’d like to point out that in my case, my session timeout callback  
> method attempts to redirect\_to somewhere no matter what. I have to  
> always return _false_ from it because everything I have is protected by  
> my authenticate filter. Since I would have a new session (created by  
> session\_timeout) and no session[:user], I would get a double  
> render/redirect error if the session timeout callback returned true and  
> allowed the authenticate filter to run.

The double render/redirect error is precisely why I keep the  
expire\_session  
filter simple. No render/redirect whatsoever. I leave it to filters down  
the  
chain (like authenticate) to pick up on the fact that the session have  
expired  
and do something with it.

> My question was about making an intelligent decision about which action  
> to redirect\_to _within_ the session timeout callback.

I was trying to say this isn’t necessary if you leave that decission to  
the  
down chain filters, like authenticate. That would be my approach and  
I do appologize for not being more helpful.

Regards,

– Long

---

<div class="post-metadata">

**Author:** ![weyus](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/w/7ab992/32.png) [@weyus](https://www.ruby-forum.com/u/weyus)\
**Post date:** [February 23, 2007, 8:38am UTC](https://www.ruby-forum.com/t/using-sessiontimeout-which-actions-need-session-data/86494/7 "2007-02-23T08:38:17Z")

</div>

I ended up doing the following:

In application.rb:

session\_times\_out\_in 4.hours, :after\_timeout =\> :handle\_session\_timeout,  
:except =\> :handle\_session\_timeout

handle\_session\_timeout is a protected method in application.rb:

def handle\_session\_timeout  
session[:session\_expiry\_notice] = ‘You have been inactive for too  
long, and your session has expired.’  
requested\_controller\_class = (controller\_name.camelize +  
‘Controller’).constantize  
if  
requested\_controller\_class.respond\_to?(‘session\_data\_not\_needed\_by?’) &&  
requested\_controller\_class.session\_data\_not\_needed\_by?(action\_name,  
params.reject {|key, value| [‘action’, ‘controller’].include?(key)})  
redirect\_to({:controller =\> controller\_name, :action =\>  
action\_name}.merge(params))  
else  
redirect\_to(:controller =\> ‘general’, :action =\>  
‘display\_open\_items’)  
end  
return false  
end

handle\_session\_timeout always returns false to ensure that a double  
render/redirect doesn’t occur.

Each controller that contains any methods which _do not_ require session  
data to be available in order to function properly has a class method  
like the following:

def self.session\_data\_not\_needed\_by?(action\_name, params)  
[‘start\_quote’, ‘display\_quotes’].include?(action\_name) ||  
(action\_name == ‘requote’ && (! params.empty?))  
end

Basically, when the session expires, we figure out if the action can  
proceed normally (based on the session\_data\_not\_needed\_by? method) and  
if so, we proceed. Otherwise, we go to a predefined “default” action  
where the user can start over (in this case general/display\_open\_items).

---

<div class="post-metadata">

**Author:** ![weyus](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/w/7ab992/32.png) [@weyus](https://www.ruby-forum.com/u/weyus)\
**Post date:** [February 23, 2007, 2:10am UTC](https://www.ruby-forum.com/t/using-sessiontimeout-which-actions-need-session-data/86494/8 "2007-02-23T02:10:55Z")

</div>

Long,

That makes sense.

I am attempting to send people back to where they wanted to go _when I  
can do that_ from the timeout callback. I have this working. But I  
realize that I could probably set it up so that the authenticate filter  
handles that.

I think my approach is clean in the sense that the authenticate filter  
is still only responsible for authenticating and doesn’t need to be  
concerned about “doing the work” of the session timeout callback.

Thanks for all the help,  
Wes
