1

关于在 Heroku 上部署 Sinatra 应用程序,我对实际上不是一个实际问题(只是一个概念难题)感到困惑。

我有两个应用程序,几乎在各个方面都相同,除了一个将其大部分逻辑放在一个不包含 Sinatra::Base 类的文件中,并使用“需要其他文件名”来获取它需要的逻辑。该 Sinatra:Base 类名为 Kincalc。

对于在一个文件中包含所有逻辑的应用程序(即包含 Sinatra:Base 类的同一文件),在我的 config.ru 文件中,最后一行显示“运行 Sinatra::Application”,它可以正常启动。但是在另一个应用程序中,如果我将其作为最后一行,该应用程序会正确上传并说它已“部署到 Heroku”,但会显示“未找到”消息。当我将最后一行读取为“运行 Kincalc”时,它可以正常加载。

我已经来回检查了这一点,这两个应用程序的构建方式没有什么不同,除了一个为逻辑使用第二个文件(也位于根目录)的事实。为什么这会是个问题,或者这真的是个问题?当我尝试将第二个文件(没有 Sinatra 类的文件)放在单独的 lib 文件夹中时,当我调用类名时它仍然有效,但当我调用“Sinatra::Application”时它仍然有效。

4

1 回答 1

7

顶层代码将委托给Sinatra::Application,因此这将是运行经典应用程序的场景:

# app.rb
require 'sinatra'

get '/' do
  'hi'
end

# config.ru
require './app'
run Sinatra::Application

如果你定义一个模块化应用程序,你会像这样运行它:

# app.rb
require 'sinatra/base'

class Kincalc < Sinatra::Base
  get '/' do
    'hi'
  end
end

# config.ru
require './app'
run Kincalc

现在我假设你想要做的是:

# otherfilename.rb
require 'sinatra'

get '/' do
  'hi'
end

# app.rb
require 'sinatra/base'

class Kincalc < Sinatra::Base
  require './otherfilename'
end

# config.ru
require './app'
run Kincalc # Sinatra::Application seems to work

您遇到的行为(获取 404 File Not Found)实际上是正确的,因为require不关心它被调用的词法范围。查看以下示例

# a.rb
puts "in a, top level: #{self.inspect}"

module Example
  puts "in a, nested: #{self.inspect}"
  require 'b'
end

# b.rb
puts "in b: #{self.inspect}"

结果输出应该是:

in a, top level: main
in a, nested: Example
in b: main

因此,如果您想使用一个模块化应用程序,您应该执行以下操作:

# otherfilename.rb
Kincalc.get '/' do
  'hi'
end

或再次打开课程:

# otherfilename.rb
class Kincalc
  get '/' do
    'hi'
  end
end

或者您实际上otherfilename.rb可以Sinatra::ApplicationKincalc.

# app.rb
require 'sinatra/base'
require './otherfilename'

class Kincalc < Sinatra::Base
  use Sinatra::Application
end

或者您可以更改将顶级 DSL 方法委托给的位置:

# app.rb
require 'sinatra/base'

class Kincalc < Sinatra::Base
  Sinatra::Delegator.target = self
  require './otherfilename'
end
于 2012-04-20T08:53:50.333 回答