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

Ada*_*sek 42 rack middleware ruby-on-rails conventions

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

目前我已经确定了,app/middleware但我可以轻松地将其移至vendor/middleware或者vendor/plugins/middleware......

最大的问题是必须要求顶部的单个文件 config/environment.rb

require "app/middleware/system_message"
require "app/middleware/rack_backstage"
Run Code Online (Sandbox Code Playgroud)

或者我在线上得到未初始化的常量错误config.middleware.use.这可能会很快变得混乱.我宁愿将它隐藏在某个地方的初始化器中.

这个东西有传统的地方吗?


我正在寻找的具体答案是:我可以在哪里放置需求行,以便它们不会混乱environment.rb文件,但仍然在config.middleware.use调用之前加载?我尝试过的所有内容都会导致未初始化的常量错误.


更新:现在我们正在使用Rails 3.0,我像任何其他Rack应用程序一样对待Rails应用程序; 中间件的代码文件进入lib(或列出的宝石Gemfile)并且是必需的和加载的config.ru.

Mik*_*ema 48

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

它在没有任何明确的require语句的情况下"开箱即用".

快速举例:

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

config.middleware.use CanonicalHost, "example.com"
Run Code Online (Sandbox Code Playgroud)

如果您要向application.rb添加中间件,则需要包含引号,根据@ mltsy的评论.

config.middleware.use "CanonicalHost", "example.com"
Run Code Online (Sandbox Code Playgroud)

  • 您能否添加任何链接以供参考?它对我来说不是开箱即用的,谷歌/ Rails指南没有帮助......谢谢! (4认同)
  • 注意:如果你在一个环境特定的文件中添加中间件(即`production.rb`),这只能工作(没有引号) - 如果你想通过把它放在`application.rb`中将它添加到所有环境中,你必须使用引号(或明确要求定义类的文件),因为在任何动态初始化代码加载`app/middleware`文件之前,application.rb是首先加载的东西之一. (4认同)
  • 请注意,在 Rails 5+ 中,您不能再使用 String 作为中间件的名称。您需要使用正确的类名。此外,根据 @rafaelfranca(Rails 核心)的说法,_“中间件不能位于应用程序中,因为它们无法重新加载。它们应该位于 lib 中,如果你将它们放入 lib 中,则 require_relative 将起作用。”_ https:/ /github.com/rails/rails/issues/25525#issuecomment-479941866 (2认同)

Chr*_*ald 23

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

config.middleware.use "MyApp::TotallyAwesomeMiddleware"
Run Code Online (Sandbox Code Playgroud)

你会留在:

lib/my_app/totally_awesome_middleware.rb
Run Code Online (Sandbox Code Playgroud)

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

>> ChrisHeald::StdLib.to_s.tableize.singularize
=> "chris_heald/std_lib"
Run Code Online (Sandbox Code Playgroud)

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


Cra*_*ker 11

在我的Rails 3.2应用程序中,我能够TrafficCop通过将其放入中间件来加载app/middleware/traffic_cop.rb,就像@MikeJarema所描述的那样.然后我config/application.rb按照指示将此行添加到我的行中:

config.middleware.use TrafficCop
Run Code Online (Sandbox Code Playgroud)

但是,在应用程序启动时,我不断收到此错误:

uninitialized constant MyApp::Application::TrafficCop
Run Code Online (Sandbox Code Playgroud)

明确指定根命名空间也无济于事:

config.middleware.use ::TrafficCop
# uninitialized constant TrafficCop
Run Code Online (Sandbox Code Playgroud)

出于某种原因(我还没有发现),在Rails生命周期的这一点上,app/middleware未包含在加载路径中.如果我删除了该config.middleware.use行,并运行了控制台,我可以TrafficCop毫无问题地访问该常量.但它app/middleware在配置时无法找到它.

我通过将中间件类名称括在引号中来修复此问题,如下所示:

config.middleware.use "TrafficCop"
Run Code Online (Sandbox Code Playgroud)

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


yfe*_*lum 5

对于 Rails 3:

#config/application.rb
require 'lib/rack/my_adapter.rb'
module MyApp
  class Application < Rails::Application
    config.middleware.use Rack::MyAdapter
  end
end
Run Code Online (Sandbox Code Playgroud)