您将 Rack 中间件文件和需求放在哪里?

发布于 2024-09-13 02:55:07 字数 714 浏览 9 评论 0原文

我正在将 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 应用程序视为任何其他 Rack 应用程序;中间件的代码文件位于 lib 中(或 Gemfile 中列出的 gem),并且需要并在 config.ru 中加载。

I'm in the process of refactoring some logic built into a Rails application into middleware, and one annoyance I've run into is a seeming lack of convention for where to put them.

Currently I've settled on app/middleware but I could just as easily move it to vendor/middleware or maybe vendor/plugins/middleware...

The biggest problem is having to require the individual files at the top of config/environment.rb

require "app/middleware/system_message"
require "app/middleware/rack_backstage"

or else I get uninitialized constant errors on the config.middleware.use lines. That could get messy very quickly. I'd rather this was tucked away in an initializer somewhere.

Is there a conventional place to put this stuff?


The specific answer I'm looking for with this bounty is: where can I put the require lines so that they are not cluttering the environment.rb file but still get loaded before the config.middleware.use calls? Everything I have tried leads to uninitialized constant errors.


Update: Now that we're using Rails 3.0, I treat a Rails app like any other Rack app; code files for middleware go in lib (or a gem listed in Gemfile) and are required and loaded in config.ru.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

情栀口红 2024-09-20 02:55:07

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

它“开箱即用”,无需任何明确的 require 语句。

简单的例子:

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

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

:将中间件添加到 application.rb 中,您需要包含引号,按照 @mltsy 的评论

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

As of Rails 3.2, Rack middleware belongs in the app/middleware directory.

It works "out-of-the-box" without any explicit require statements.

Quick example:

I'm using a middleware class called CanonicalHost which is implemented in app/middleware/canonical_host.rb. I've added the following line to production.rb (note that the middleware class is explicitly given, rather than as a quoted string, which works for any environment-specific config files):

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

If you're adding middleware to application.rb, you'll need to include quotes, as per @mltsy's comment.

config.middleware.use "CanonicalHost", "example.com"
眼泪淡了忧伤 2024-09-20 02:55:07

您可以将其放在lib/tableized/file_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_heald/std_lib.rb 中,并且当我在代码中引用它时会自动加载。

You can put it in lib/tableized/file_name.rb. As long as the class you're trying to load is discoverable by its filename, Rails will automatically load the file necessary. So, for example:

config.middleware.use "MyApp::TotallyAwesomeMiddleware"

You would keep in:

lib/my_app/totally_awesome_middleware.rb

Rails catches const_missing and attemts to load files corresponding to the missing constants automatically. Just make sure your names match and you're gravy. Rails even provides nifty helpers that'll help you identify the path for a file easily:

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

So my stdlib lives in lib/chris_heald/std_lib.rb, and is autoloaded when I reference it in code.

熟人话多 2024-09-20 02:55:07

在我的 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"

这样,我就可以避免 未初始化常量 错误,因为 Rails 不会尝试查找 TrafficCop刚刚上课。但是,当它开始构建中间件堆栈时,它将常量化该字符串。此时,app/middleware 已位于加载路径中,因此该类将正确加载。

In my Rails 3.2 app, I was able to get my middleware TrafficCop loading by putting it at app/middleware/traffic_cop.rb, just as @MikeJarema described. I then added this line to my config/application.rb, as instructed:

config.middleware.use TrafficCop

However, upon application start, I kept getting this error:

uninitialized constant MyApp::Application::TrafficCop

Explicitly specifying the root namespace didn't help either:

config.middleware.use ::TrafficCop
# uninitialized constant TrafficCop

For some reason (which I've yet to discover), at this point in the Rails lifecycle, app/middleware wasn't included in the load paths. If I removed the config.middleware.use line, and ran the console, I could access the TrafficCop constant without any issue. But it couldn't find it in app/middleware at config time.

I fixed this by enclosing the middleware class name in quotes, like so:

config.middleware.use "TrafficCop"

This way, I would avoid the uninitialized constant error, since Rails isn't trying to find the TrafficCop class just yet. But, when it starts to build the middleware stack, it will constantize the string. By this time, app/middleware is in the load paths, and so the class will load correctly.

ゝ杯具 2024-09-20 02:55:07

对于 Rails 3:

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

For Rails 3:

#config/application.rb
require 'lib/rack/my_adapter.rb'
module MyApp
  class Application < Rails::Application
    config.middleware.use Rack::MyAdapter
  end
end
诗化ㄋ丶相逢 2024-09-20 02:55:07

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

I'm not aware of a convention, but why not put it in the /lib directory? Files in there get automatically loaded by Rails.

相守太难 2024-09-20 02:55:07

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

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

You could create an initializer which requires the necessary files and then leave the files wherever you want.

According to this the initializers are executed before the rack middleware is loaded.

请远离我 2024-09-20 02:55:07

到目前为止,我的工作解决方案是将中间件需求移至 config/middleware.rb 并要求该文件位于environment.rb 中,将其减少为我可以的单个需求住在一起。

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

The working solution I have so far is moving the middleware requires to config/middleware.rb and requiring that file in environment.rb, reducing it to a single require which I can live with.

I'd still like to hear how other people have solved this seemingly basic problem of adding middleware to Rails.

天生の放荡 2024-09-20 02:55:07

接受的答案不再有效。中间件不应该位于 /app 中,因为它们可以'无需重新加载

它们应该位于 /lib 中并显式加载,例如

/lib/middleware/system_message.rb

module Middleware
  class SystemMessage
    # ...
  end
end

/config/application.rb

require_relative '../lib/middleware/system_message'

# ...

config.middleware.use Middleware::SystemMessage

The accepted answer is no longer valid. Middlewares should not be in /app because they can't be reloaded.

They should be in /lib instead and loaded explicitly, e.g.

/lib/middleware/system_message.rb

module Middleware
  class SystemMessage
    # ...
  end
end

/config/application.rb

require_relative '../lib/middleware/system_message'

# ...

config.middleware.use Middleware::SystemMessage
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文