Wednesday, August 4, 2010

Sharing Sessions Between Rails 2 and Rails 3 Applications

I have been working on writing new applications in Rails 3 at work, but up until this week, they weren't at a point where I would actually interact with my existing applications since they were just in development. However, this week, I was at a point where I could start working on the integration.

The main thing that needs to happen between applications is I have a central authentication/authorization application that I share the session secret key and the user database with my other applications to serve as a sort-of single sign-on set up. It has worked well enough to this point, but I had always been running applications at approximately the same version of Rails 2 on all of the applications.

The first step is to configure the applications to use the same domain and secret key.

On my rails2 app, I had a config like in config/initializers/session_store.rb:



And then in config/environments/development.rb



Originally in my Rails 3 app, I had something in the config/initializer/session_store.rb like this:



But, I found that it just wasn't taking the session at all. After much combing through the Rails 2 and 3 source to see why, I finally found this in the Changelog:

*Rails 3.0.0 [beta 3] (April 13th, 2010)*

* Renamed config.cookie_secret to config.secret_token and pass it as env key. [JV]


*Rails 3.0.0 [beta 2] (April 1st, 2010)*

* Session store configuration has changed [YK & CL]

    config.session_store :cookie_store, {:key => "..."}
    config.cookie_secret = "fdsfhisdghfidugnfdlg"


OK, that was a pretty quiet, but major change.. and it only caused me a few hours of grief. But, I made those changes..



And in the RC for Rails 3, they have moved the secret token into its own initializer at config/initializers/secret_token.rb. Since I created the application using beta4, I didn't see this.

First issue fixed. When I got that I was able to see the session being passed, but now ran into a new problem from the Rails 2 app.

I got the very useful error message:

ActionController::SessionRestoreError in User sessionsController#new

Session contains objects whose class definition isn\'t available.
Remember to require the classes for all objects kept in the session.
(Original exception: #{const_error.message} [#{const_error.class}])

Some more time spent with irb and I found that it was passing the Rails 3 flash class of ActionDispatch::Flash::FlashHash and Rails 2 didn't know about that since it uses ActionController::Flash::FlashHash, and abstract_store.rb has code to check to make sure that a class that is set in the session is a known, and since the classes are different for flash messages bewteen Rails 2 and Rails 3, this alert was generated.

OK, rather than monkey patching Rails 2 to know about ActionDispatch, I just decided to go the easier route and just not set the flash message. I did get a similar problem with my Rails 2 application setting the flash and getting a similar (but fixed) error message about not having ActionController::Flash::FlashHash, but easily enough fixed by just removing the flash messages.

Ultimately, the solution is going to be to get everything upgraded to Rails 3, but hopefully someone who is going through similar pains will find this useful since the solutions aren't always obvious with error messages and stack traces.

Update: Another solution instead of just removing flash messages, is to use flash.now, which shouldn't put the flash messages in the session.

3 comments:

  1. I am facing the same problem of sharing session between rails2 and rails3 application , my rails2 app authenticates user and create session and redirect to rails3 application and here i got this
    'Session contains objects whose class definition isn\'t available.'
    i have commented all flash in my rails2 app still i got this error.
    Somebody help me

    ReplyDelete
  2. Hi Dan,

    Thanks for your article. I'm facing the same problem trying to share sessions between Rails 2.3.8 and 3.0.1. However, none of the solutions you're suggesting worked for me. I'm wondering if you have any new thoughts on this?

    ReplyDelete
  3. Hello Dan,

    I dived deeper into the problem and wrote a post about it. Hopefully this will come in handy, thanks again for making my job a little easier.
    You can find the post at http://blog.kabisa.nl/2010/10/27/share-sessions-between-rails-2-and-rails-3-applications/

    ReplyDelete