-
-
Save jimweirich/847634 to your computer and use it in GitHub Desktop.
| # This is a fragment of code from action_controller/request.rb that handles sessions. | |
| # (this is Rails 2.3.11 if that matters). | |
| # It is obvious from the first method that a session is expected to be a hash. | |
| def session | |
| @env['rack.session'] ||= {} | |
| end | |
| def session=(session) #:nodoc: | |
| @env['rack.session'] = session | |
| end | |
| # But, if session is a hash, what is "session.destroy" expected to do? | |
| # I'm confused. | |
| def reset_session | |
| session.destroy if session | |
| self.session = {} | |
| end | |
| # We are actually hitting the session.destroy line when session is a normal looking hash. | |
| # I don't understand how this code is even correct. |
The rails session is not expected to be an ActiveRecord::Base object. Even when the session is ActiveRecord based, we have an object that wraps an instance of ActiveRecord. So, what is happening?
Rack initializes the session as a hash but it is later replaced by a SessionHash object (which responds to destroy) in the session middleware:
After you reset the session, it sets a hash back. The obvious bug here is that if you call reset_session twice, it will raise an error. It has been fixed in Rails 3-0-stable and master (but it seems it was not backported):
The session middleware explicitly checks if the session is a hash, and, if so, it serializes it completely back. When the SessionHash object is in the session, it tries to be a bit smarter and just serializes it back if something was written and so on.
Taking a peek at this thread..
https://rails.lighthouseapp.com/projects/8994/tickets/6440-session-reset-undefined-method-destroy-for-hash
It points to this file being the potential culprit...
actionpack-2.3.11/lib/action_controller/session/abstract_store.rb