require "mongo_session_store/mongo_store_base" module ActionDispatch module Session class MongoStore < MongoStoreBase class Session class << self attr_writer :database def load(options = {}) options[:data] = options["data"] if options["data"] options[:data] = if options[:data] unpack(options[:data]) else {} end new(options) end def where(query = {}) collection.find(query).map { |doc| load(doc) } end def database return @database if @database raise NoMongoClientError, "MongoStore needs a database, e.g. "\ "MongoStore::Session.database = Mongo::Client.new("\ "[\"127.0.0.1:27017\"], database: \"my_app_development\")" end def collection @collection ||= database[MongoSessionStore.collection_name] end def reset_collection @collection = nil end private def unpack(packed) return unless packed data = packed.respond_to?(:data) ? packed.data : packed.to_s Marshal.load(StringIO.new(data)) end end class NoMongoClientError < ::MongoSessionStore::Error; end attr_accessor :_id, :data, :created_at, :updated_at def initialize(options = {}) @_id = options[:_id] @data = options[:data] @created_at = options[:created_at] @updated_at = options[:updated_at] end def save @created_at ||= Time.now.utc @updated_at = Time.now.utc scope.replace_one(attributes_for_save, :upsert => true) end def destroy scope.delete_one end private def collection self.class.collection end def attributes_for_save { :data => pack(data), :created_at => created_at, :updated_at => updated_at } end def scope collection.find(:_id => _id) end def pack(data) BSON::Binary.new(Marshal.dump(data || {}), :generic) end def unpack(packed) self.class.unpack(packed) end end end end end MongoStore = ActionDispatch::Session::MongoStore