Manual access to session data outside of request?

So, given a sessionID, I have need to read and write the session stored
information ‘manually’, from outside an actual Rails
request/controller.

Readers, I know your first response may be to tell me I don’t really
want to do that. Trust me though, I really do, it makes sense for me in
my case.

I know this wouldn’t work if you’re using the new cookie session storage
mechanism. But if you’re using a server-side session storage mechanism,
I’m thinking there must be some reasonable way to do this. But I’m
having trouble figuring it out.

I’ve tried looking through the rails source code to see how Rails reads
and write session, but I’m having trouble finding the relevant code. I
also figured, gee, since Rails allows pluggable session storage
architecture, there must be an abstract description of what a session
store must implement, and how to access it, and that might help me –
but I couldn’t find that either.

Anyone have any ideas or tips? I’d like a
session-storage-implementation-agnostic (assuming it’s a server-side
method of storage) way to read and write the session hash from outside a
Rails controller.

Jonathan

On 20 Apr 2009, at 17:04, Jonathan R. wrote:

also figured, gee, since Rails allows pluggable session storage
architecture, there must be an abstract description of what a session
store must implement, and how to access it, and that might help me –
but I couldn’t find that either.

How it is stored is almost all up to the session store - they need to
be able to fetch the data for a given session id and store some data
for a session id.

The details have changed between rails 2.2 and 2.3, in 2.2 it was the
old cgi interface, in 2.3 it’s the new rack interface - you’ll need to
instantiate the appropriate subclass of ActionController::SessionStore

Fred

Frederick C. wrote:

The details have changed between rails 2.2 and 2.3, in 2.2 it was the
old cgi interface, in 2.3 it’s the new rack interface - you’ll need to
instantiate the appropriate subclass of ActionController::SessionStore

This helps, thanks. Trying to look through the source and googling, I
did discover that this changed very much between 2.2 and 2.3, I might
need to write two versions of my code.

But since there is an abstract model for a session store, it must be
possible for me to access the session store and read and write session
info without knowing about the black box internals.

Once I’ve gotten the appropriate ActionController::SessionStore… what
the heck do I do with it in order to read or write session data?

Unless the specs for how to write a session store have changed in 2.3,
it may be my code doesn’t need to be different for 2.3. But if it does,
I can deal with that too.

Still having trouble figuring out what methods to call on a session
store once I’ve gotten it to read or write data.

Frederick C. wrote:

Unless the specs for how to write a session store have changed in 2.3,
it may be my code doesn’t need to be different for 2.3. But if it does,
I can deal with that too.

They did - had to rewrite a lot of that bit of my session store for
2.3

Thanks Fred. It actually looks like this would be fairly straightforward
in 2.3. This blog post provides some hints:

http://devblog.michaelgalero.com/2009/02/03/guide-to-rails-metal/

But my app is not yet working with 2.3 in general, and I’d like it to
work with both. And in pre-2.3, it seems, from looking at the Rails
source, that it would be REALLY tricky to do this.

So now I’m thinking of another option. One would be storing this
information in my own database models, keyed by Rails SessionID. But
once I’ve done that, I’ve kind of duplicated the ActiveRecordStore. So
another option would be writing my code to assume that the session store
is an ActiveRecordStore – if you make this assumption, instead of
trying to write store-agnostic code, then accessing the info in pre-2.3
looks to be more do-able. And I could write code that works with either
pre 2.3 or 2.3.

Not sure what I’m going to do really. I need something keyed on
sessionID that is accessible outside a Rails request, as well as inside
a Rails request.

If anyone else has ideas, feel free to share.

Jonathan

On Apr 20, 6:13 pm, Jonathan R. <rails-mailing-l…@andreas-
s.net> wrote:

possible for me to access the session store and read and write session
info without knowing about the black box internals.

Once I’ve gotten the appropriate ActionController::SessionStore… what
the heck do I do with it in order to read or write session data?

Unless the specs for how to write a session store have changed in 2.3,
it may be my code doesn’t need to be different for 2.3. But if it does,
I can deal with that too.

They did - had to rewrite a lot of that bit of my session store for
2.3

In 2.3 Session stores have to implement a get_session method. The
first argument is just the environment hash that rack gives you -
you’ll probably have to fiddle around a bit to workout how much you
have to fake up (maybe nothing at all)

Fred

Frederick C. wrote:

On 20 Apr 2009, at 19:31, Jonathan R. wrote:
2.2 is a bit easier actually -

I must admit that my app is still in Rails 2.1 now, for annoying reasons
that will make everyone tell me I’m doing Rails wrong again.

If you assume ActiveRecord store it’s pretty easy. find the row with
the right session id, data is right there.

Yeah, I think that’s the way to go for now. I’d like to use
ActiveRecordStore’s own methods to serialize/unserialize the data, to
not have my code depending on certain assumptions about precisely how
ActiveRecordStore serializes, but I think that’s do-able too.

Thanks for helping me think this through.

Jonathan

On 20 Apr 2009, at 19:31, Jonathan R. wrote:

2.2 is a bit easier actually -

Struct.new(‘FakeSession’, :session_id)
fake_cgi_session = Struct::FakeSession.new(‘some session id’)

session = WhateverSessionStoreClass.new(fake_cgi_session)
session.restore

Fred

pre 2.3 or 2.3.

If you assume ActiveRecord store it’s pretty easy. find the row with
the right session id, data is right there.

Fred

On Apr 20, 8:11 pm, Jonathan R. <rails-mailing-l…@andreas-
s.net> wrote:

Frederick C. wrote:

On 20 Apr 2009, at 19:31, Jonathan R. wrote:
2.2 is a bit easier actually -

I must admit that my app is still in Rails 2.1 now, for annoying reasons
that will make everyone tell me I’m doing Rails wrong again.

the pre 2.2 way should work way back to rails 1.1, and possibly even
further back.

Fred

If you assume ActiveRecord store it’s pretty easy. find the row with
the right session id, data is right there.

Yeah, I think that’s the way to go for now. I’d like to use
ActiveRecordStore’s own methods to serialize/unserialize the data, to
not have my code depending on certain assumptions about precisely how
ActiveRecordStore serializes, but I think that’s do-able too.

Jonathan R. wrote:

Ah, but I guess now I have your sample code to read a session. Do you
have any similar magic code to write it back out to the store? I guess I
can probably figure it out for myself now that I know the magic way to
fake a cgi session.

Ha, I’ve made it work! Now I just need to do it for rails 2.3 too, to
have it both ways.

But here’s the rails pre-2.3 version. Thanks Fred!

Struct.new(‘FakeSession’, :session_id)

  # Craziness to restore a session in Rails pre 2.2. Will most 

likely
# need to be changed for Rails 2.2.

  fake_cgi_session = Struct::FakeSession.new('some session id')

  session_obj = 

ActionController::Base.session_store.new(fake_cgi_session)
@session = session_obj.restore

  # Later, you've modified the hash and want to save it back to 

store?
# just:

  session_obj.close

You want to save something, just modify that hash, and then call

Frederick C. wrote:

the pre 2.2 way should work way back to rails 1.1, and possibly even
further back.

Huh, then I might as well do it the actual legit way, and I guess I can
now easily do this in a storage-agnostic manner for both pre 2.2 and
2.2. Nice, thanks for supplying that sample code Fred, after a couple
hours looking through the Rails source I wasn’t any closer to figuring
it out for myself.

Ah, but I guess now I have your sample code to read a session. Do you
have any similar magic code to write it back out to the store? I guess I
can probably figure it out for myself now that I know the magic way to
fake a cgi session.

Jonathan

Frederick C. wrote:

Struct.new(‘FakeSession’, :session_id)
fake_cgi_session = Struct::FakeSession.new(‘some session id’)

session = WhateverSessionStoreClass.new(fake_cgi_session)
session.restore

Okay, pre-Rails-2.2, if you want to fake a session and you want to have
it work to create a new session with that ID even if one doesn’t
currently exist, and you sometimes use an ActiveRecord session store
(phew), then instead of simply using a Struct to create a duck-typed
fake session, you need something that will implement new_session too,
still using the same session_id.

class FakeSession
attr_accessor :session_id
def initialize(a_session_id)
self.session_id = a_session_id
end
def new_session
return self.session_id
end
end

Frederick C. wrote:

2.2 is a bit easier actually -

Struct.new(‘FakeSession’, :session_id)
fake_cgi_session = Struct::FakeSession.new(‘some session id’)

session = WhateverSessionStoreClass.new(fake_cgi_session)
session.restore

Fred

Revisiting old history. Huh, I swear I had this working before in Rails
2.1, but I return to it to finish it off and now it does not.

on the .new(fake_cgi_session) call, I get:

NoMethodError: private method `new_session’ called for #

I probably just need to get my app working in 2.3, where this is all
much more consistent and rational.