I was wondering why FileStore converts the values of the session’s hash into
String objects before saving them? (Refer to the methods ‘update’ and
’restore’.) It is frustrating having to convert everything back from
strings all of the time.
Couldn’t we use marshaling and get the actual objects back? This would also
make FileStore work in the same way that MemoryStore does, which seems like
a Good Thing.
Is there a reason it wasn’t done this way in the first place?
In message “CGI::Session::FileStore question” on 02/11/07, “Chris” nemo@hellotree.com writes:
I was wondering why FileStore converts the values of the session’s hash into
String objects before saving them? (Refer to the methods ‘update’ and
‘restore’.) It is frustrating having to convert everything back from
strings all of the time.
Couldn’t we use marshaling and get the actual objects back? This would also
make FileStore work in the same way that MemoryStore does, which seems like
a Good Thing.
Is there a reason it wasn’t done this way in the first place?
Marshal may not be what you want before saving data. So do it by
yourself, or wrap CGI::Session::FileStore to do marshaling. It is not
too hard to define something like CGI::Session::PStore. Sufficient
for your homework.
Couldn’t we use marshaling and get the actual objects back? This would
also
make FileStore work in the same way that MemoryStore does, which seems like
a Good Thing.
Is there a reason it wasn’t done this way in the first place?
Marshal may not be what you want before saving data. So do it by
yourself, or wrap CGI::Session::FileStore to do marshaling. It is not
too hard to define something like CGI::Session::PStore. Sufficient
for your homework.
matz.
···
----- Original Message -----
My homework? You lost me there…
Anyway, I don’t really understand why Marshal might not be a good idea.
Performance?
Plus, it still seems like FileStore and MemoryStore should be
interchangable, and they definitely aren’t right now.
In any case, I threw something together which seems to work pretty well. It
was saving and loading Fixnums, booleans, Arrays of strings… much better
than saving all of your session data in strings, IMHO.
I also added a function to Session to get the hash object, because there are
other Hash functions I would like to be able to use (‘clear’ and ‘replace’
in particular) on the session data, and because I wanted the program logic
to be as separate as possible from the web interface. Passing a Hash
reference seemed more orthogonal than passing a Session reference. (I might
want to run this from other interfaces in the future.)
class CGI
class Session
def getHash
if (!@data) @data = @dbman.restore
end @data
end
class FileStore
def restore
unless @hash
@hash = {}
@f.flock File::LOCK_EX
@f.rewind
k = nil
for line in @f
line.chomp!
if (!k)
k = line
else
v = Marshal::load(CGI::unescape(line))
@hash[CGI::unescape(k)] = v
k = nil
end
end
end
@hash
end
def update
return unless @hash
@f.rewind
for k,v in @hash
v = Marshal::dump(v)
@f.printf "%s\n", CGI::escape(k)
@f.printf "%s\n", CGI::escape(v)
end
@f.truncate @f.tell
end
end
It is not too hard to define something like CGI::Session::PStore.
Sufficient for your homework.
i think this is not directly possible because of = in CGI::Session we have
def =(key, val)
unless @write_lock @write_lock = true
end
unless @data @data = @dbman.restore
end @data[key] = String(val) # <— problem here?
end
seems like this should only be
@data[key] = val
and left to the individual dbman to stringify, or not. i did create a working
PStoreStore by making this change (baby unit test included) but i thought one
should not have to change CGI::Session
require ‘cgi/session’
require ‘pstore’
class CGI
class Session
def =(key, val)
unless @write_lock @write_lock = true
end
unless @data @data = @dbman.restore
end
#@data[key] = String(val) @data[key] = val
end
class PStoreStore
def check_id(id)
/[^0-9a-zA-Z]/ =~ id.to_s ? false : true
end
def initialize session, option={}
dir = option['tmpdir'] || ENV['TMP'] || '/tmp'
prefix = option['prefix'] || ''
id = session.session_id
unless check_id(id)
raise ArgumentError, "session_id `%s' is invalid" % id
end
path = dir+"/"+prefix+id
path.untaint
unless File::exist? path
@hash = {}
end
@p = PStore.new path
end
def restore
unless @hash
@p.transaction do
begin
@hash = @p['hash']
rescue
@hash = {}
end
end
end
@hash
end
def update
@p.transaction do
@p['hash'] = @hash
end
end
def close
update
end
def delete
path = @p.path
File::unlink path
end
end
end
Ara Howard
NOAA Forecast Systems Laboratory
Information and Technology Services
Data Systems Group
R/FST 325 Broadway
Boulder, CO 80305-3328
Email: ahoward@fsl.noaa.gov
Phone: 303-497-7238
Fax: 303-497-7259
====================================
So this is what I add to my web scripts:
[snip]
Thoughts?
[snip]
why modify FileStore? does it make sense to escape/unescape arbitrary objects?
it does for FileStore since all it takes are Strings, but why bother for normal
object key/value?
i was thinking something like :
require ‘cgi/session’
require ‘pstore’
class CGI
class Session
class PStoreStore < FileStore
def initialize cgi, options={}
super @p = PStore.new @f.path
end
def restore @p.transaction do
begin @hash = @p[‘hash’]
rescue @hash = {}
end
end @hash
end
def update @p.transaction do @p[‘hash’] = @hash
end
end
end
end
end
the other FileStore methods do not need to be overidden.
-a
···
On Fri, 8 Nov 2002, Chris wrote:
–
====================================
Ara Howard
NOAA Forecast Systems Laboratory
Information and Technology Services
Data Systems Group
R/FST 325 Broadway
Boulder, CO 80305-3328
Email: ahoward@fsl.noaa.gov
Phone: 303-497-7238
Fax: 303-497-7259
====================================
In message “Re: CGI::Session::FileStore question” on 02/11/09, ahoward ahoward@fsl.noaa.gov writes:
@data[key] = String(val) # <— problem here?
seems like this should only be
@data[key] = val
and left to the individual dbman to stringify, or not. i did create a working
PStoreStore by making this change (baby unit test included) but i thought one
should not have to change CGI::Session