Sharing sessions between a rails3 app and a rails2 app. Rails 2 app crashes

Hey all.

I have two apps. One is a rails3 app and the other is a rails 2 app.
Using proxying I am routing actions in the myapp.com/foo to the rails2
app.

It almost works! I can set a session variable and a cookie variable on
the first app (myapp.com) and then read them on the second app
(myapp.com/foo).

It only works the first time though. If I go back to myapp.com and
then revisit myapp.com/foo the rails2 application crashes with the
error NameError (uninitialized constant
ActiveSupport::HashWithIndifferentAccess):

This error is raised when any attempt to access the session variable is
made.

I first thought it was because rails3 set a session[‘session_id’] and
rails2 set a session[:session_id] so wrote some code to delete
session[‘session_id’] but that didn’t solve the problem.

The setup is pretty straightforward. They both use cookie sessions
(for now). They both have the same key, secret and domain. nginex does
the proxying.

So what is going on here? Any clues? Why does it work the first time
but crash if you hit the back button and the forward button?

you should share some code here, there could be many reasons for that

On Tue, Aug 24, 2010 at 7:04 AM, gkaykck [email protected] wrote:

you should share some code here, there could be many reasons for that

Ok it’s pretty simple.

In rails 2 app I have something like this.

Initializers session_store.rb

ActionController::Base.session_store = :cookie_store

ActionController::Base.session = {
:key => ‘_session_identifier’,
:secret => secret

}

enviroment.rb

config.action_controller.session = {

      :domain     => '.domain.name'

}

In the rails 3 application I have this.

Rails.application.config.session_store :cookie_store, :key =>
‘_session_identifier’, :domain => “.domain.name”
Rails.application.config.secret_token = secret
Rails.application.config.cookie_secret = secret

in the rails3 app I set the variables like this

session[‘tim’] = ‘This is a session variable’
cookies[‘tim’] = ‘This is a cookie variable’

in the rails2 app

@tim = session[‘tim’]
@cookie = cookies[‘tim’]

The steps needed to crash the rails 2 app.

go to domain.name
cookies and session variables are set
go to subdomain name
cookie and session variable is read properly
go back to domain name, reload
go back to subdomain, reload
the applicaiton crashes

ActiveSupport::HashWithIndifferentAccess in your rails 2 app

I’ll give that a try and see if it works.

Another thing I noticed was that rails3 sets a ‘session_id’ and rails2
sets a :session_id

I don’t know why they changed that.

On Aug 23, 2:21 am, Tim U. [email protected] wrote:

It only works the first time though. If I go back to myapp.com and
then revisit 应用宝官网-全网最新最热手机应用游戏下载 the rails2 application crashes with the
error NameError (uninitialized constant
ActiveSupport::HashWithIndifferentAccess):

This error is raised when any attempt to access the session variable is made.

Well it looks like the core issue is that HashWithIndifferentAccess
became ActiveSupport::HashWithIndifferentAccess in rails 3. The
session is a serialized ruby object which somewhere is saying that it
contains an instance of class ActiveSupport::HashWithIndifferentAccess
and rails 2 is complaining that it doesn’t know what that is.
From what you’ve said I’m not sure why it works the first time. It
could be that something on the second request is storing such a hash
or that a development mode class loading oddity means that initially
ActiveSupport::HashWithIndifferentAccess is able to find the top level
class. You may be able to solve this by defining
ActiveSupport::HashWithIndifferentAccess in your rails 2 app

Fred

I’ll give that a try and see if it works.

Another thing I noticed was that rails3 sets a ‘session_id’ and rails2
sets a :session_id

Just to follow up on this…

Your workaround worked but it only went so far. Now I am getting this
error.

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}])

I am not going to chase this down. Who knows what object it’s
complaining about. I think I am just going to set a cookie and track
it on the other app. That part seems to be working OK.

I hope this saves somebody lots of work.

Tim

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}])

This is because the class definition for flash notifications changed.
You can see this discussed at

If you can stop using flash notifications, that is one “solution”. We’re
trying to figure out a better fix.

The suggestion to use flash.now[:notice] is only going to work if there
is no redirect between setting the message and rendering it.

I think the best hack, although ugly, will be to make rails2 and rails3
both aware of the class that the other one uses for flashes. They don’t
need to deal with it, just have a class definition.

Brad

Just an update to this. I was trying to do the same thing, specifically
have a Rails3 app read some state from the session set by Rails2. I got
it working by doing what Brad M. suggested, making Rails3 aware of the
Rails2 class that was missing.

I included the definition of ActionController::Flash in a file that got
loaded at startup. It was necessary to comment out two calls to
alias_chain_method right at the start of the code. It appears this works
for Rails3 to read what Rails2 has put into the session, and that’s all
I need to do.

I’m not going to push it any further but suspect this might provide
others with a migration strategy.