30

In ruby on rails when doing session[:foo] = nil it leaves an entry named :foo in the session object. How can you get rid of that single entry from the session object?

aarona
  • 35,986
  • 41
  • 138
  • 186
Jim Soho
  • 2,018
  • 2
  • 21
  • 25

3 Answers3

81

It looks like the simplest version works. All stores (Cookie, File, ActiveRecord, ...) use AbstractStore::SessionHash as the object that contains the data, the different stores provide only the means to load and save the AbstractStore::SessionHash instances.

AbstractStore::SessionHash inherits from Hash, so this defers to the Hash#delete method:

session.delete(:key_to_delete)
Daniel Beardsley
  • 19,907
  • 21
  • 66
  • 79
  • 1
    Looks like they changed the behaviour. This didn't work in Rails 2.3, as far as I remember. Thanks! – iGEL Dec 20 '11 at 13:53
8

Actually there is a way to get delete a value from the session. Like RichH said the session variable is a CGI::Session instance. When enter something like session[:foo] it is actually looking that symbol up in a @data instance variable in the session object. That data variable is a hash.

EDIT: There is a data instance variable in the CGI::Session class. If you go to the docs and look at the source code for the []= method you'll see that there is a @data member.

So to delete session[:foo] all you have to do is access that @data variable from inside the session

   session.data[:foo]

Now to delete it:

   session.data.delete :foo

Once you do this the there should be no more foo in your session variable.

vrish88
  • 20,047
  • 8
  • 38
  • 56
  • Is that portable accross all of the session stores? It looks a little intimate as the data attribute isn't mentioned in the docs. – RichH Mar 26 '09 at 08:19
  • I honestly don't know. I discovered it by using debugger and inspecting the session variable. I was able to find a little support for my answer though, http://tinyurl.com/cp7ntm, check out the last method where they assign session_data = @_session.data. That's the most I could find on it – vrish88 Mar 26 '09 at 09:14
  • I just updated my answer with a much better source for some documentation on the subject. – vrish88 Mar 26 '09 at 09:40
  • That's just the ActiveRecord store - if you look at the cookie store, memcache store, etc they don't have this attr_reader - http://github.com/rails/rails/blob/31ce92f7b5784bc5b6a441e88cd734c7b8b1c58f/actionpack/lib/action_controller/session/cookie_store.rb – RichH Mar 26 '09 at 15:10
  • The way I understand it is that the CGI::Session:CookieStore is an extension of the CGI::Session class. So CookieStore would inherit everything in CGI::Session. When we modify the Session class (by adding @data to it) we inherit all those changes into the extensions that follow it (CookieStore) – vrish88 Mar 26 '09 at 16:23
  • @data isn't in the base Session class it's in the active record session store - that's the source you pointed to. The memcached session doesn't use @data, it uses an @cache to store the session contents. ActiveRecord does something different to. This is implementation specific. – RichH Mar 26 '09 at 17:53
  • Ok @data may not be in the rdoc for CGI::Session but if you take a look at the actual code for the '[]=' method, http://tinyurl.com/djoltc, you'll see that a @data instance variable is created or written to. So for certain session stores Rails will overwrite the @data variable. – vrish88 Mar 26 '09 at 22:16
2

As the Session is a Ruby CGI::Session and not a Hash, calling delete will actually delete session. Delete takes no parameters - this is my you're getting the "wrong number of arguments (1 or 0)" message when you try what hyuan suggests.

The generally accepted way to clear a session entry is with session[:foo] = nil as you suggest. It is far from ideal, but statements like session[:foo].nil? will behave as expected.

I really wish it behaved like a normal Hash ... but it doesn't.

RichH
  • 6,108
  • 1
  • 37
  • 61