【问题标题】:make object available in sinatra scope使对象在 sinatra 范围内可用
【发布时间】:2013-01-30 12:09:02
【问题描述】:

在 sinatra 中我有以下内容:

config = YAML.load_file('sinatra_resources/server.yml')
usernamedk = config["dkuser"]
passworddk = config["dkpass"]
passwordse = config["sepass"]
usernamese = config["seuser"]
database = config["database"]

cpooldk = OCI8::ConnectionPool.new(1, 5, 2, usernamedk, passworddk, database)
cpoolse = OCI8::ConnectionPool.new(1, 5, 2, usernamese, passwordse, database)

当我在路由中使用这些值中的任何一个时,它都可以正常工作。但是我想在函数中使用它们,当我引用这些变量等时。

作为我的问题的一个例子,如果我有一个函数

def getuser(lang)
 if lang == "se" then
   return usernamese
 else
   return usernamedk
end

并且在我拥有的路线内 用户 = 获取用户(语言)

然后当我尝试使用 lang = "se" 调用它时,我发现变量 usernamese 未定义.. 同样的事情适用于我想在多个路由之间共享的函数中使用的所有变量。

我尝试了以下方法: 配置做

set :env, "local"

set :usernamedk, config["dkuser"]
set :passworddk, config["dkpass"]
set :passwordse, config["sepass"]
set :usernamese, config["seuser"]
set :database, config["database"]

set :cpooldk, OCI8::ConnectionPool.new(1, 5, 2, setting.usernamedk, setting.passworddk, setting.database)
set :cpoolse,  OCI8::ConnectionPool.new(1, 5, 2, setting.usernamese, setting.passwordse, setting.database)

end

但我得到了错误 undefined local variable or method `usernamedk' for main:Object (NameError)

【问题讨论】:

  • 变量范围在您的 getuser 示例中是本地的。变量不可用。你能显示更多代码吗?您使用的是经典模式还是模块化模式?
  • 我同意@jordelver,您应该提供更多代码,因为您正在谈论范围,但很难知道问题出在哪里。例如,函数在哪里定义?这一切都在一个文件中并且您使用的是 Sinatra 的经典模式吗?
  • 这一切都在一个文件中,所以我想从这里sinatrarb.com/extensions.html 它将被视为经典模式。我最终只是创建了一堆全局变量,因为这让我可以做我想做的事 - 以前没有考虑过,而且拥有这么多全局变量也是一种非常糟糕的形式。

标签: ruby sinatra


【解决方案1】:

当您可以访问配置作为哈希时,为什么还要麻烦所有变量?

configure do
  # no need to set the env as local if you're trying to affect the scope

  config = YAML.load_file('sinatra_resources/server.yml')
  set :config, config

  set :cpooldk, OCI8::ConnectionPool.new(1, 5, 2, config["dkuser"], config["dkpass"], config["database"])
  set :cpoolse, OCI8::ConnectionPool.new(1, 5, 2, config["seuser"], config["sepass"], config["database"])
end

helpers do
  def getuser(lang)
    if lang == "se" then
      settings.config["seuser"] # no need for the explicit returns in Ruby
    else
      settings.config["dkuser"]
    end
  end
end

get "/some-route" do
  get_user("se")
end

【讨论】:

    【解决方案2】:

    您的变量只有本地范围,它们不是实例变量。您可以通过在 @ 前添加前缀(例如 @ usernamedk)将它们用作实例变量,或者您可以将所有这些变量用作设置(参见 https://github.com/sinatra/sinatra#configuration):

    configure do
      set :usernamedk = config["dkuser"]
      set :passworddk = config["dkpass"]
      set :passwordse = config["sepass"]
      set :usernamese = config["seuser"]
      set :database = config["database"]
    end
    
    def getuser(lang)
      if lang == "se" then
        return settings.usernamese
      else
        return settings.usernamedk
    end
    

    希望有帮助

    【讨论】:

    • 我从文档中猜想应该设置它:usernamedk, config["dkuser"] 但是如果我尝试以下操作:configure do set :env, "local" set :usernamedk, config[ “dkuser”] 设置:passworddk,配置 [“dkpass”] 设置:密码,配置 [“sepass”] 设置:用户名,配置 [“seuser”] 设置:数据库,配置 [“数据库”] 设置:cpooldk,OCI8: :ConnectionPool.new(1, 5, 2, setting.usernamedk, setting.passworddk, setting.database) 结束或变化我得到未定义的局部变量或方法 `usernamedk' 为 main:Object
    猜你喜欢
    • 2011-04-25
    • 2017-06-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-03
    • 1970-01-01
    • 2012-02-27
    • 2021-02-01
    相关资源
    最近更新 更多