require 'rack/session/abstract/id' require 'active_support/cache' module Telegram module Bot class UpdatesController # Add functionality to store data between requests. module Session extend ActiveSupport::Concern def process_action(*) super ensure session.commit end protected def session @_session ||= begin key = session_key key ? SessionHash.new(self.class.session_store, key) : NullSessionHash.new end end def session_key subject = from || chat "#{bot.username}:#{subject['id']}" if subject end # Rack::Session::Abstract::SessionHash is taken to provide lazy loading. # All methods that access store are overriden to support # ActiveSupport::Cache::Store stores. class SessionHash < Rack::Session::Abstract::SessionHash attr_reader :id def initialize(store, id) @store = store @id = id end def destroy clear @store.delete(id) end def exists? return @exists if defined?(@exists) @data = {} @exists = @store.exist? id end def load! session = @store.read(id) @data = session ? stringify_keys(session) : {} @loaded = true end def commit return unless loaded? data = to_hash.delete_if { |_, v| v.nil? } @store.write(id, data) end end class NullSessionHash < Session::SessionHash def initialize @data = {} @loaded = true @exists = true end alias_method :destroy, :clear alias_method :load!, :id alias_method :commit, :id end module ConfigMethods delegate :session_store, to: :config def session_store=(store) config.session_store = ActiveSupport::Cache.lookup_store(store) end def use_session! include Session end end end end end end