tag:blog.hasmanythrough.com,2006-02-27:/tag/sessionshas_many :through - sessions2007-01-12T07:40:00-08:00tag:blog.hasmanythrough.com,2006-02-27:Article/712007-01-12T07:40:00-08:002008-01-24T00:19:34-08:00Don't make a new one on my accountJosh Susser<p>Here's a fairly obscure but useful trick to optimize session usage in Rails. I can pretty safely bet that you haven't used it yet because it was broken until two weeks ago when, with bloody forehead, I discovered the bug that had been causing me to bang my head repeatedly on the table. Big kudos to Jeremy Kemper for assisting in the speedy fix. Anyway, where was I?</p>
<p>Oh yeah. Sessions.</p>
<p>Sessions are mostly useless. There, I said it. I'd guess that at least 95% of the time all people are using sessions for in Rails are flash messages and setting the :user_id of authenticated users. If your app doesn't authenticate users or have some other unusual need for sessions, it's a pretty painful waste of that overhead to use them only for flash messages.</p><p>Here's a fairly obscure but useful trick to optimize session usage in Rails. I can pretty safely bet that you haven't used it yet because it was broken until two weeks ago when, with bloody forehead, I discovered the bug that had been causing me to bang my head repeatedly on the table. Big kudos to Jeremy Kemper for assisting in the speedy fix. Anyway, where was I?</p>
<p>Oh yeah. Sessions.</p>
<p>Sessions are mostly useless. There, I said it. I'd guess that at least 95% of the time all people are using sessions for in Rails are flash messages and setting the :user_id of authenticated users. If your app doesn't authenticate users or have some other unusual need for sessions, it's a pretty painful waste of that overhead to use them only for flash messages.</p>
<p>One of the nice things about how <a href="http://mephistoblog.com/">Mephisto</a> is designed is that only authenticated users get a session when they login to the admin console. (Yes, there are no flash messages.) That means that the kajillions of guest users who are just reading a blog don't get a session. And that removes a lot of overhead from serving up pages, especially when most of the pages are cached as static HTML (yay for Rails' page caching!). I think that was a great decision, but it became a pain when I decided I wanted to highlight comments I made in my own blog as special so readers could easily see which comments were mine.</p>
<p>The problem was that the main controller is configured with <code>session :off</code>, so no session was available to check to see if there was an authenticated user making the comment. Now, the admin controller has sessions on, so if I had already logged in on the admin console I'd have a session_id cookie in the browser, and the main controller could just notice it there and use it to get the commenter's user id to mark the comment as special. At least in theory. But you can't see an existing session with sessions turned off in your controller!</p>
<p>It turns out there is a lovely option on the <code>session</code> directive for controllers.</p>
<pre><code>LazyController < ActiveController::Base
session :new_session => false
# ...
end
</code></pre>
<p>Using the <code>:new_session => false</code> option tells Rails not to create a new session if there isn't one already, but if there is, go ahead and use it. That's exactly what I needed, and it ended up working perfectly to let me hack Mephisto to mark my comments as special. (At least it did after Jeremy and I fixed the crashing bug.) If you use this option and there is no previously existing session, the session will appear as an empty hash. You can set values in that hash, but they won't stick around to the next action.</p>
<p>You can see the special comments in action right here in my blog - just look around. You can also use that feature in your own Mephisto blog, since Rick accepted my patch and now trunk will do that for you too. Check out <a href="http://mephisto.stikipad.com/help/show/Special+comment+styles">the wiki page</a> on how to do it.</p>
<p>And if you're not using Mephisto, you can still use the <code>:new_session => false</code> option to lighten the load on your web app. I think this is potentially very useful for RESTful apps. I like the idea of blending admin functions into the normal content UI. This way you can have sessionless guest users and still provide authorized admin features on public pages.</p>