你在哪里放置你的Rack中间件文件并要求?

时间:2010-08-06 22:51:28

标签: ruby-on-rails conventions rack middleware

我正在将构建在Rails应用程序中的一些逻辑重构为中间件,而我遇到的一个烦恼似乎是缺乏将它们放在哪里的约定。

目前我已确定app/middleware,但我可以轻松将其移至vendor/middlewarevendor/plugins/middleware ...

最大的问题是必须要求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,我会像任何其他Rack应用程序一样对待Rails应用程序;中间件的代码文件放在lib(或Gemfile中列出的gem)中,并且必须加载到config.ru

7 个答案:

答案 0 :(得分:48)

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

它没有任何明确的需求声明,可以“开箱即用”。

快速举例:

我正在使用名为 CanonicalHost 的中间件类,该类在 app / middleware / canonical_host.rb 中实现。我已将以下行添加到production.rb( note 中,明确指定了中间件类,而不是作为引用字符串,适用于任何特定于环境的配置文件):

config.middleware.use CanonicalHost, "example.com"

如果您要将中间件添加到 application.rb ,则需要根据@mltsy's comment添加引号。

config.middleware.use "CanonicalHost", "example.com"

答案 1 :(得分:23)

您可以将其放入lib/tableized/file_name.rb。只要您尝试加载的类可以通过其文件名发现,Rails将自动加载必要的文件。所以,例如:

config.middleware.use "MyApp::TotallyAwesomeMiddleware"

你会留在:

lib/my_app/totally_awesome_middleware.rb

Rails捕获const_missing和attemts以自动加载与缺少的常量相对应的文件。只要确保你的名字匹配,你就是肉汁。 Rails甚至提供了漂亮的帮助程序,可以帮助您轻松识别文件的路径:

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

所以我的stdlib住在lib/chris_heald/std_lib.rb,当我在代码中引用它时会自动加载。

答案 2 :(得分:11)

在我的Rails 3.2应用程序中,我可以通过将其放在TrafficCop来获取我的中间件app/middleware/traffic_cop.rb,就像@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"

这样,我会避免uninitialized constant错误,因为Rails还没有尝试找到TrafficCop类。但是,当它开始构建中间件堆栈时,它将对字符串进行constantize。到目前为止,app/middleware位于加载路径中,因此类将正确加载。

答案 3 :(得分:4)

对于Rails 3:

#config/application.rb
require 'lib/rack/my_adapter.rb'
module MyApp
  class Application < Rails::Application
    config.middleware.use Rack::MyAdapter
  end
end

答案 4 :(得分:0)

我不知道一个约定,但为什么不把它放在/lib目录中呢?其中的文件由Rails自动加载。

答案 5 :(得分:0)

您可以创建一个初始化程序,它需要必要的文件,然后将文件保留在您想要的任何位置。

根据this,初始化程序在加载机架中间件之前执行。

答案 6 :(得分:0)

我到目前为止的工作解决方案是将中间件需要移动到config/middleware.rb并要求environment.rb中的文件,将其减少到我可以使用的单个需求。

我还是想听听其他人如何解决将这些中间件添加到Rails这个看似基本的问题。