12

机架指定

Rack 应用程序是响应调用的 Ruby 对象(不是类)。

因此,一个简单的config.ru看起来像这样:

class MyApp
  def call(env)
    [200, {"Content-Type" => "text/plain"}, ["Hello from Rack!\n"]]
  end
end

run MyApp.new

而 Rails 生成这个:

# This file is used by Rack-based servers to start the application.

require ::File.expand_path('../config/environment',  __FILE__)
run RailsApp::Application

所以,我想知道:为什么不run RailsApp::Application.new将 Rack 指定为对象而不是类?Rails::Application我错过了什么特别的东西吗?

4

2 回答 2

19

这确实有点隐藏:)

RailsApp::Application是 的子类Rails::Application,而后者又是 a Rails::Enginewhich 是 a Rails::Railtie。现在Rails::Railtie有一个inherited钩子,只要子类从 Railtie 类继承(在本例中Engine),就会调用该钩子。

此回调将Rails::Railtie::Configurable模块包含到子类中。在这个模块中,你会发现魔法的第一部分。

在类上定义的method_missing方法调用类实例上的方法,或多或少地解析为

RailsApp::Application.new.call(...)

call实例方法Rails::Application#call在典型的 Rack 处理中定义并执行。

可能还涉及到更多的魔法,这使得它不是 100% 等价的,但大致应该是这样......

于 2013-03-22T15:00:13.753 回答
1

一个类也是一个对象。Rack 不实例化应用程序对象(这就是它指定您需要提供对象的原因),您在 中执行此操作config.ru,因此当 Rack 发送“调用”时,如果 Rails 类对象遵循所有 Rack 规则,它不应该是问题。

在内部,我不知道 Rails 是否对call. 它甚至可以是一个工厂方法,既吐出应用程序类的实例并运行它。但这并不需要满足 Rack。

于 2013-03-22T14:55:16.467 回答