Ruby on rails 您将机架中间件文件和要求放在何处?

Ruby on rails 您将机架中间件文件和要求放在何处?,ruby-on-rails,conventions,rack,middleware,Ruby On Rails,Conventions,Rack,Middleware,我正在将Rails应用程序中内置的一些逻辑重构为中间件,我遇到的一个麻烦是,似乎缺少将它们放在何处的约定 目前我已经决定使用应用程序/中间件,但我可以很容易地将其移动到供应商/中间件或供应商/插件/中间件 最大的问题是必须在config/environment.rb require "app/middleware/system_message" require "app/middleware/rack_backstage" 否则我会在config.middleware.use行上得到未初始化的

我正在将Rails应用程序中内置的一些逻辑重构为中间件,我遇到的一个麻烦是,似乎缺少将它们放在何处的约定

目前我已经决定使用
应用程序/中间件
,但我可以很容易地将其移动到
供应商/中间件
供应商/插件/中间件

最大的问题是必须在
config/environment.rb

require "app/middleware/system_message"
require "app/middleware/rack_backstage"
否则我会在
config.middleware.use
行上得到未初始化的常量错误。这很快就会变得一团糟。我宁愿把它藏在某个地方的初始值中

有没有一个传统的地方可以放这些东西


我想从这份赏金中找到的具体答案是:我可以把require行放在哪里,这样它们就不会弄乱environment.rb文件,但仍然会在config.middleware.use调用之前加载?我尝试的所有操作都会导致未初始化的常量错误



更新:现在我们使用的是Rails 3.0,我将Rails应用程序视为其他机架应用程序;中间件的代码文件位于
lib
(或
Gemfile
中列出的gem)中,并且是必需的,并加载在
config.ru
我不知道有一个约定,但为什么不将其放在
/lib
目录中呢?Rails会自动加载其中的文件。

您可以创建一个需要必要文件的初始值设定项,然后将这些文件保留在任何需要的地方


根据所述,初始值设定项在加载机架中间件之前执行

到目前为止,我的工作解决方案是将中间件要求移动到
config/middleware.rb
,并在
environment.rb
中要求该文件,将其简化为我可以接受的单一要求

我仍然想听听其他人是如何解决向Rails添加中间件这一看似基本的问题的。

对于Rails 3:

#config/application.rb
require 'lib/rack/my_adapter.rb'
module MyApp
  class Application < Rails::Application
    config.middleware.use Rack::MyAdapter
  end
end
#config/application.rb
需要'lib/rack/my_adapter.rb'
模块MyApp
类应用程序
您可以将其放入
库/表格化/文件\u name.rb
。只要您试图加载的类可以通过其文件名发现,Rails就会自动加载所需的文件。例如:

config.middleware.use "MyApp::TotallyAwesomeMiddleware"
您将继续:

lib/my_app/totally_awesome_middleware.rb
Rails捕获const_missing并尝试自动加载与丢失的常量对应的文件。只要确保你的名字匹配,你就是肉汁。Rails甚至提供了漂亮的助手,帮助您轻松识别文件路径:

>> ChrisHeald::StdLib.to_s.tableize.singularize
=> "chris_heald/std_lib"

因此,我的stdlib位于
lib/chris\u heald/std\u lib.rb
,当我在代码中引用它时,它会自动加载。

从Rails 3.2开始,机架中间件属于app/middleware目录

它是“开箱即用”的,没有任何明确的require语句

快速示例:

我正在使用一个名为CanonicalHost的中间件类,它在app/middleware/canonical\u host.rb中实现。我已经在production.rb中添加了以下行(注意中间件类是显式给出的,而不是作为带引号的字符串,它适用于任何特定于环境的配置文件):

如果要将中间件添加到application.rb,则需要根据添加引号


在我的Rails 3.2应用程序中,我能够通过将其放置在
app/middleware/traffic_cop.rb
来加载中间件
TrafficCop
,正如@MikeJarema所描述的那样。然后,我按照说明将这一行添加到我的
config/application.rb

config.middleware.use TrafficCop
但是,在应用程序启动时,我不断遇到以下错误:

uninitialized constant MyApp::Application::TrafficCop
显式指定根命名空间也没有帮助:

config.middleware.use ::TrafficCop
# uninitialized constant TrafficCop
出于某种原因(我还没有发现),在Rails生命周期的这一点上,
app/middleware
没有包含在加载路径中。如果我删除了
config.middleware.use
行并运行控制台,我就可以访问
TrafficCop
常量而不会出现任何问题。但在配置时,它在
app/middleware
中找不到它

我通过将中间件类名括在引号中解决了这个问题,如下所示:

config.middleware.use "TrafficCop"

这样,我就避免了
未初始化常量
错误,因为Rails还没有试图找到
TrafficCop
类。但是,当它开始构建中间件堆栈时,它将使字符串保持不变。此时,
app/middleware
已在加载路径中,因此该类将正确加载。

除非在运行environment.rb之后(如果有的话)。将它们移动到lib并没有解决未初始化的常量错误。看起来我在阅读时有点乐观。我猜config.ru也不符合您的要求?嗯,这需要使用rackup而不是script/server,对吗?如果有必要的话,我可以这样做,但我真的认为这样做会更容易。我有一些中间件叫做
Rack::Backstage
。把它放在
lib/rack/backstage.rb
中。单位化常量错误。仅当第一个参数是字符串时,此操作才有效。一旦我明白了,成功!你能添加任何链接供参考吗?这对我来说不是开箱即用的,Google/Rails指南也帮不上忙。。。谢谢当我意识到我犯了一个愚蠢的错误,把它放在我的根文件夹而不是(已经指定的)应用程序文件夹中时,我马上就把它做好了。因此,foo_app/app/middleware/file.rb。我必须将我的中间件类名括在引号中才能使其正常工作;请参阅下面我的答案。注意:只有在特定于环境的文件(即
production.rb
)中添加中间件时,这才有效(不带引号)-如果要通过将中间件放入
application.rb
,将其添加到所有环境中,则必须使用引号(或明确要求定义类的文件),b
config.middleware.use ::TrafficCop
# uninitialized constant TrafficCop
config.middleware.use "TrafficCop"