64 lines
1.7 KiB
Ruby
64 lines
1.7 KiB
Ruby
module ActionDispatch
|
|
module Session
|
|
class MongoidStore < AbstractStore
|
|
|
|
class Session
|
|
include Mongoid::Document
|
|
include Mongoid::Timestamps
|
|
|
|
field :data, :type => String, :default => [Marshal.dump({})].pack("m*")
|
|
index :updated_at
|
|
end
|
|
|
|
# The class used for session storage.
|
|
cattr_accessor :session_class
|
|
self.session_class = Session
|
|
|
|
SESSION_RECORD_KEY = 'rack.session.record'.freeze
|
|
|
|
private
|
|
def generate_sid
|
|
BSON::ObjectId.new
|
|
end
|
|
|
|
def get_session(env, sid)
|
|
sid ||= generate_sid
|
|
session = find_session(sid)
|
|
env[SESSION_RECORD_KEY] = session
|
|
[sid, unpack(session.data)]
|
|
end
|
|
|
|
def set_session(env, sid, session_data)
|
|
record = env[SESSION_RECORD_KEY] ||= find_session(sid)
|
|
record.data = pack(session_data)
|
|
# Rack spec dictates that set_session should return true or false
|
|
# depending on whether or not the session was saved or not.
|
|
# However, ActionPack seems to want a session id instead.
|
|
record.save ? sid : false
|
|
end
|
|
|
|
def find_session(id)
|
|
id = BSON::ObjectId.from_string(id.to_s)
|
|
@@session_class.first(:conditions => { :_id => id }) ||
|
|
@@session_class.new(:id => id)
|
|
end
|
|
|
|
def pack(data)
|
|
[Marshal.dump(data)].pack("m*")
|
|
end
|
|
|
|
def unpack(packed)
|
|
return nil unless packed
|
|
Marshal.load(packed.unpack("m*").first)
|
|
end
|
|
|
|
def destroy(env)
|
|
session = @@session_class.first(:conditions => { :_id => env[SESSION_RECORD_KEY].id })
|
|
session.try(:destroy)
|
|
|
|
env[SESSION_RECORD_KEY] = nil
|
|
end
|
|
|
|
end
|
|
end
|
|
end |