Singleton can't be dumped

I ran into a new error today, and after digging around my code for a bit, I figured out what was going on. I have an after_filter in my ApplicationController called set_last_url. It came from the session handling code in active_record_store, and its contents look like this:

class ApplicationController < ActionController::Base
  after_filter :set_last_url

  def set_last_url
    session[:last_url] = params
  end
end

For normal purposes, this method should be fine. Its purpose is to capture the last place you visited, and redirect you back after logging in or creating a new account. However, the params hash doesn't always contain information you'd like to store in the session object. In my case, it was an uploaded file. Here is the error along with a snippet of the backtrace:

Processing ItemsController#create (for 127.0.0.1 at 2007-08-12 16:09:38) [POST]
Session ID: 7797d006f6d7668e81a16564043e064f
Parameters: {"action"=>"create", "list_id"=>"1", "controller"=>"items", 
             "item"=>{"name"=>"Futurama", "price"=>"1.00", "url"=>"http://www.futurama.com", 
             "description"=>"DVD Set", "image"=>#}}

TypeError (singleton can't be dumped):
    /usr/local/lib/ruby/gems/1.8/gems/actionpack-1.13.3/lib/action_controller/session/active_record_store.rb:83:in `dump'
    /usr/local/lib/ruby/gems/1.8/gems/actionpack-1.13.3/lib/action_controller/session/active_record_store.rb:83:in `marshal'
    /usr/local/lib/ruby/gems/1.8/gems/actionpack-1.13.3/lib/action_controller/session/active_record_store.rb:135:in `marshal_data!'
    …

I had two options that became readily apparent: I could change my code such that I only store the controller, action, and possibly ID parameters into the session object. Unfortunately, sometimes I add parameters to the end of my query string, and I don't want to omit them from the redirect URL. The other option was to act on the request method, which is what I ended up doing. In practice, I realized I didn't need to set the last URL after calls that were anything except GET, so I edited my filter definition a bit:

class ApplicationController < ActionController::Base
  after_filter :set_last_url

  def set_last_url
    session[:last_url] = params if request.get?
  end
end

No more error!

Leave a Reply