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?
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
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
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
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
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.
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.
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.