【问题标题】:Sinatra Session data shared between browsers浏览器之间共享的 Sinatra 会话数据
【发布时间】:2015-10-05 03:34:43
【问题描述】:

我有一个使用 Sinatra 在 Heroku 上运行的基本银行应用程序。

我已尝试实施会话以确保访问的每个用户都拥有不同版本的应用。但是,目前,如果我用两个不同的浏览器访问它,我有相同的数据。

没有实现后端数据库,但我通过接口添加的数据会保留在我访问的每个浏览器中。

这是我的app.rb

require 'sinatra/base'
require 'tilt/erb'
require 'require_all'
require_all 'lib'
require 'rufus-scheduler'

class BankingApp < Sinatra::Base

  enable :sessions
  set :session_secret, 'super secret'

  get '/' do
    session[:accounts] = AccountsController.instance
    session[:holders]  = HoldersController.instance
    session[:loans]    = LoansController.instance 
    erb :index
  end

  get '/holders' do
    @holders = session[:holders].store
    erb :holders
  end

  get '/holders_accounts' do
    @holder = session[:holders].find(params[:id].to_i)
    message = session[:accounts].get_accounts_of(params[:id].to_i)
    @accounts = message.accounts
    erb :holders_accounts
  end

  get '/new_holder' do
    erb :new_holder
  end

  post '/new_holder' do
    @message = session[:holders].create(params[:name])
    @holders = session[:holders].store
    erb :holders
  end

  get '/create_account' do
    erb :create_account
  end

  post '/create_account' do
    type = :Current
    id = params[:id].to_i
    @message = session[:accounts].open(type, with: id)
    erb :index
  end

  get '/accounts' do
    @accounts = session[:accounts].store
    erb :accounts
  end

  get '/transactions' do
    message = session[:accounts].get_transactions_of(params[:id].to_i)
    @transactions = message.transactions
    erb :transactions
  end

  get '/deposit' do
    erb :deposit
  end

  post '/deposit' do
    @accounts = session[:accounts].store
    @message = session[:accounts].deposit(params[:amount].to_i, into: params[:id].to_i)
    erb :accounts
  end

  get '/withdraw' do
    erb :withdraw
  end

  post '/withdraw' do
    @accounts = session[:accounts].store
    @message = session[:accounts].withdraw(params[:amount].to_i, from: params[:id].to_i)
    erb :accounts
  end

  get '/transfer' do
    erb :transfer
  end

  post '/transfer' do
    @accounts = session[:accounts].store
    @message = session[:accounts].transfer(params[:amount].to_i, from: params[:donar].to_i, to: params[:recipitent].to_i)
    erb :accounts
  end

  get '/add_holder' do
    erb :add_holder
  end

  post '/add_holder' do
    @accounts = session[:accounts].store
    @message = session[:accounts].add_holder(params[:holder_id].to_i, to: params[:account_id].to_i)
    erb :accounts
  end

  get '/enable_overdraft' do
    erb :enable_overdraft
  end

  post '/enable_overdraft' do
    @accounts = session[:accounts].store
    @message = session[:accounts].activate_overdraft(params[:id].to_i, params[:amount].to_i)
    erb :accounts
  end

  get '/disable_overdraft' do
    erb :disable_overdraft
  end

  post '/disable_overdraft' do
    @accounts = session[:accounts].store
    @message = session[:accounts].deactivate_overdraft(params[:id].to_i)
    erb :accounts
  end

  get '/loans' do
    @loans = session[:loans].store
    erb :loans
  end

  get '/loan_view' do
    message = session[:loans].show(params[:id].to_i)
    @transactions = message.transactions
    erb :loan_view
  end

  get '/new_loan' do
    erb :new_loan
  end

  post '/new_loan' do
    @loans = session[:loans].store
    id = params[:id].to_i
    options = { borrowed: params[:amount].to_i, term: params[:term].to_i, rate: params[:rate].to_f }
    @message = session[:loans].create_loan(id, options)
    erb :loans
  end

  get '/pay_loan' do
    erb :pay_loan
  end

  post '/pay_loan' do
    @message = session[:loans].pay(params[:amount].to_i, off: params[:id].to_i)
    @loans = session[:loans].store
    erb :loans
  end

  # start the server if ruby file executed directly
  run! if app_file == $0
end

我对 Sinatra 没有丰富的经验,如果这是我的疏忽,我深表歉意。

非常感谢任何帮助。

【问题讨论】:

  • 您能否分享更多关于您在此处尝试实现的目标以及您采用这种方法的原因。这里有很多不是 Sinatra 或 Ruby 惯用的,结合我们看不到的所有代码(例如,控制器的定义),很难有把握地说出什么是坏的还是什么是以非标准方式实施。编辑:刚刚注意到代码在 GitHub 上,我会去那里看看 :)

标签: ruby session heroku sinatra


【解决方案1】:

我会推荐使用这个

get '/logout' 做

session.clear

结束

【讨论】:

    【解决方案2】:

    所以我很确定您的问题的核心是this line,您在整个代码中的多个位置都有它。根据ruby docs

    这确保只能创建一个 Klass 实例。

    您已经明确告诉 ruby​​ 只允许每个类/模块的一个副本存在。我不认为那是你想要的。

    很难准确地推断出您想要实现的目标是什么,但我认为在 Web 应用程序中使用 Singleton 不会是正确的解决方案。一旦您运行应用程序的第二个实例(或 Heroku 术语中的 dyno),它所施加的假设就会失效。

    【讨论】:

    • 感谢您的回复。我使用了 Singleton 类,以便我可以在每个控制器中引用每个控制器的单个实例。让控制器相互通信。有没有更有效的方法来做到这一点?
    • @robertpulson from the docs "对于每个传入的请求,都会创建一个应用程序类的新实例"。要共享数据,请使用settings helper 或使用类实例变量。
    猜你喜欢
    • 2012-12-18
    • 2013-12-18
    • 2019-04-27
    • 2013-07-07
    • 2011-04-27
    • 2021-05-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多