Lighthouse has a new layout. Prefer the old one? Return to the old layout, and switch back any time from the link at the top of each page.

This project is archived and is in readonly mode.

Session Reset undefined method `destroy' for {}:Hash

#6440

After upgrading Rails to version 2.3.11 I started receiving this error after calling reset_session:

 Backtrace:


/home/deploy/apps/gems_bundler/ruby/1.8/gems/actionpack-2.3.11/lib/action_controller/request.rb:449:in 'reset_session' /home/deploy/apps/gems_bundler/ruby/1.8/gems/actionpack-2.3.11/lib/action_controller/base.rb:1244:in 'reset_session_without_flash' /home/deploy/apps/gems_bundler/ruby/1.8/gems/actionpack-2.3.11/lib/action_controller/flash.rb:159:in 'reset_session'

My first reaction was to google for a solution when I couldn't I came here and looked for related tickets and I manage to find this one:

#4938 [PATCH] Session fixes: sessions should not be created until written to; and s...

I was digging (read: trying to) for the answer and perharps for an acceptable patch but I couldn't. This was the best I could do (correct me if I'm wrong):

At first, sessions were created on each request but it was harming performance so they decided to lazy it and then ActionController::Session::AbstractStore::SessionHash was created. It extends the normal Hash class but it's extended with some methods including 'destroy' which is responsible for the error I am receiving.

For a reason I don't know, when a request is created or reseted, it's content is an empty normal Hash. It's only changed to a SessionHash farther when the method call is called from an AbstractStore instance.
I don't know why the creation still sets a normal hash to the session variable and not a SessionHash however I made a 'patch' without breaking tests and without changing this behavior.

./actionpack/lib/action_controller/session/abstract_store.rb (original):

  def session
    @env['rack.session'] ||= {}
  end

  def reset_session
    session.destroy if session
    self.session = {}
  end
./actionpack/lib/action_controller/session/abstract_store.rb (patch?):

  def session
    @env['rack.session'] ||= {}
  end

  def reset_session
    session.destroy if session && session.is_a?(ActionController::Session::AbstractStore::SessionHash)
    self.session = {}
  end

Hope it helps, and please correct me when I'm wrong.

Reported by Bruno Pinto · February 16th, 2011 @ 02:52 AM

State: new
Milestone: 2.x
Assigned to: Michael Koziarski Michael Koziarski
Importance: Low

Activity

  1. Santiago Pastorino
    Santiago Pastorino
    • Milestone set to 2.x
    • Assigned user set to Michael Koziarski
    • Importance changed from to Low

    February 16th, 2011 @ 01:32 PM

  2. Rob Di Marco
    Rob Di Marco

    I submitted a pull request that includes a unit test that illustrates the problem and a patch to fix the destroy method at https://github.com/rails/rails/pull/198

    While this is waiting to be fixed in the main tree, I have monkey patched the reset_session method like so

    # file config/initializers/rails_6440_patch.rb
    ActionController::Request.class_eval do
        def reset_session
          # session may be a hash, if so, we do not want to call destroy
          # fixes issue 6440
          session.destroy if session and session.respond_to?(:destroy)
          self.session = {}
        end
    end
    

    March 1st, 2011 @ 04:04 AM

  3. tiegz
    tiegz

    Having the same issue, +1!

    Related, it looks like you might have seen this similar issue in master and augmented your solution to match?

    #5634 reset_session in action_dispatch/http/request.rb failing in test mode

    April 1st, 2011 @ 06:41 PM