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.

There was a problem

You must be a member of this account.

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