Как сделать модульный помощник в Синатре

Я хочу создать метод внутри модуля (для группировки разума), который можно назвать module.method, что-то вроде этого:

helpers do
  module UserSession
    def logged_in?
      not session[:email].nil?
    end
    def logout!
      session[:email] = nil
    end
  end
end

но когда я пытаюсь вызвать его с помощью UserSession.logged_in?, он сказал, что logged_in не является методом UserSession

undefined метод `logged_in? ' для UserSession: Module

когда я перемещаю метод как метод UserSession:

helpers do
  module UserSession
    def self.logged_in?
      not session[:email].nil? # error
    end
    def self.logout!
      session[:email] = nil
    end
  end
end

он дает ошибку, что я не мог получить доступ к переменной session

undefined локальная переменная или метод `session 'для UserSession: Module

Какое наилучшее решение для этой проблемы?

Ответ 1

Вы можете использовать другое соглашение для метода helpers.

module UserSession
  def logged_in?
   not session[:email].nil?
  end
  def logout!
    session[:email] = nil
  end
end

helpers UserSession

get '/foo' do
  if logged_in?
    'Hello you!'
  else
    'Do I know you?'
  end
end

Определение модуля может, конечно, находиться в другом файле (require d).

За кулисами helpers <Module> выполняет include, но не просто в подклассу приложения Sinatra, которое вы используете для своего приложения. include должен быть совместим с тем, как get, post и т.д. Работают с их магией, а helpers делает это для вас.

Ответ 2

nevermind, я нашел ответ, я тоже пробовал define_method('UserSession.logged_in?'), но не повезло

Последнее, что я пробовал:

# outside helpers
class UserSession
  @@session = nil
  def initialize session
    @@session ||= session
  end
  def self.check
    throw('must be initialized first') if @@session.nil?
  end
  def self.logged_in?
    self.check
    not @@session[:email].nil?
  end
  def self.logout
    self.check
    @@session.delete :email
  end
end

но что-то нужно называть первым

before // do
  UserSession.new session
end

то он может быть использован по желанию:

get '/' do
  if UserSession.logged_in?
    # do something here
  end
end