您将 Rack 中间件文件和需求放在哪里?
我正在将 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
从 Rails 3.2 开始,Rack 中间件属于 app/middleware 目录。
它“开箱即用”,无需任何明确的 require 语句。
简单的例子:
我正在使用一个名为 CanonicalHost 的中间件类,它是在 app/middleware/canonical_host.rb 中实现的。我已将以下行添加到 production.rb (注意中间件类是明确给出的,而不是作为带引号的字符串,这适用于任何特定于环境的配置文件)
:将中间件添加到 application.rb 中,您需要包含引号,按照 @mltsy 的评论。
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):
If you're adding middleware to application.rb, you'll need to include quotes, as per @mltsy's comment.
您可以将其放在
lib/tableized/file_name.rb
中。只要您尝试加载的类可以通过其文件名发现,Rails 就会自动加载所需的文件。因此,例如:您将保留:
Rails 捕获 const_missing 并尝试自动加载与缺失常量相对应的文件。只要确保你们的名字匹配并且你们是肉汁即可。 Rails 甚至提供了漂亮的帮助程序,可以帮助您轻松识别文件的路径:
因此我的 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:You would keep in:
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:
So my stdlib lives in
lib/chris_heald/std_lib.rb
, and is autoloaded when I reference it in code.在我的 Rails 3.2 应用程序中,我可以通过将中间件
TrafficCop
放置在app/middleware/traffic_cop.rb
来加载它,正如 @MikeJarema 所描述的那样。然后,我按照指示将这一行添加到我的 config/application.rb 中:但是,在应用程序启动时,我不断收到此错误:
显式指定根命名空间也没有帮助:
出于某种原因(我还没有发现),在 Rails 生命周期的这一点上,
app/middleware
还没有包含在加载路径中。如果我删除了 config.middleware.use 行并运行控制台,我就可以毫无问题地访问 TrafficCop 常量。但在配置时它无法在app/middleware
中找到它。我通过将中间件类名括在引号中来修复此问题,如下所示:
这样,我就可以避免
未初始化常量
错误,因为 Rails 不会尝试查找TrafficCop
刚刚上课。但是,当它开始构建中间件堆栈时,它将常量化该字符串。此时,app/middleware
已位于加载路径中,因此该类将正确加载。In my Rails 3.2 app, I was able to get my middleware
TrafficCop
loading by putting it atapp/middleware/traffic_cop.rb
, just as @MikeJarema described. I then added this line to myconfig/application.rb
, as instructed:However, upon application start, I kept getting this error:
Explicitly specifying the root namespace didn't help either:
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 theconfig.middleware.use
line, and ran the console, I could access theTrafficCop
constant without any issue. But it couldn't find it inapp/middleware
at config time.I fixed this by enclosing the middleware class name in quotes, like so:
This way, I would avoid the
uninitialized constant
error, since Rails isn't trying to find theTrafficCop
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.对于 Rails 3:
For Rails 3:
我不知道约定,但为什么不将其放在
/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.您可以创建一个需要必要文件的初始化程序,然后将文件保留在您想要的任何位置。
根据 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.
到目前为止,我的工作解决方案是将中间件需求移至 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 inenvironment.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.
接受的答案不再有效。中间件不应该位于
/app
中,因为它们可以'无需重新加载。它们应该位于
/lib
中并显式加载,例如/lib/middleware/system_message.rb
/config/application.rb
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
/config/application.rb