Ruby on rails 4 向Rails 4添加自定义中间件
我有一个Rails 4示例项目(Blog),我在Ruby on rails 4 向Rails 4添加自定义中间件,ruby-on-rails-4,rack,rack-middleware,Ruby On Rails 4,Rack,Rack Middleware,我有一个Rails 4示例项目(Blog),我在config/initializers/request\u timer.rb #config/initializers/request_timer.rb class RequestTimer
config/initializers/request\u timer.rb
#config/initializers/request_timer.rb
class RequestTimer
def initialize(app)
@app = app
end
def call(env)
start_time = Time.now
status, headers, response = @app.call(env)
stop_time = Time.now
[status, headers, response.body]
end
end
我以两种方式在config/application.rb
中添加了中间件
1)作为常量添加
#config/application.rb
module Blog
class Application < Rails::Application
config.middleware.use RequestTimer
end
end
原因是什么?我正在使用Rails4.0.2
和rack-1.5.2
和ruby 2.0.0p247
config/initializers/request_timer.rb
移动到lib/request_timer.rb
文件夹require\u relative'../lib/request\u timer'
行添加到application.rb
文件中config.middleware.use“RequestTimer”更改为config.middleware.use RequestTimer
。不要使用引号李>
我记得,如果不在application.rb
,我们就不能使用initializers文件夹中的类
关于。NoMethodError(未定义的方法'each'for#)
,您应该确保response.body
响应'each'方法,但其类是字符串。您可以这样修复代码:[状态,标题,[response.body]
Ruby 1.9不再在String类中使用每个
要使用Rack,请提供一个“app”:一个响应调用方法的对象,将环境散列作为参数,并返回一个包含三个元素的数组:
*HTTP响应代码
*标题的散列
*响应主体,必须对每个进行响应
解决这个问题更简单的方法是将您的请求\u timer.rb
放入
app/middleware/request\u timer.rb
,然后将中间件作为字符串添加到config/application.rb
中。您应该将中间件类放在app/middleware文件夹中。添加的中间件应注入rails默认添加的中间件列表中
注意:您可以从代码中的任何位置插入中间件,但最好在为应用程序添加的任何初始值设定项中插入中间件
例如,要在rails内置中间件params解析器之后插入中间件,请执行以下操作:
Rails.application.middleware.insert_after ActionDispatch::ParamsParser, "RequestTimer"
此外,您还可以向中间件传递所需的参数,例如:
options = { :foo => 'bar' }
Rails.application.middleware.insert_after ActionDispatch::ParamsParser, "SecuredClient", options
然后,您可以在中间件中访问这些参数,如下所示:
class RequestTimer
def initialize(app, params)
@app = app
@params = params
end
end
谢谢@onurozgurozkhan!我想这取决于Rails的版本。对于Rails 3.x,我使用了def call(env)@app.call env end这是Rails 5+的绝对正确答案。以下是与Rails core的相关讨论:@memoht你为什么对我的答案投反对票?它已被弃用,但在rails 5中。问题是关于rails 4!你说得对。我删除了我的评论,如果允许的话,我将删除否决票。在答案中添加这样一个事实,即Rails 5中不推荐使用此选项将非常有用。注意,在Rails 5+中,您不能再使用字符串作为中间件的名称。您需要使用正确的类名。此外,根据@rafaelfranca(Rails core),“中间件不能在应用程序中,因为它们不能被重新加载。它们应该在lib中,如果你把它们放在lib中,require_relative将起作用。”注意,在Rails 5+中,你不能再使用字符串作为中间件的名称。您需要使用正确的类名。此外,根据@rafaelfranca(Rails核心)的说法,“中间件不能在应用程序中,因为它们不能被重新加载。它们应该在lib中,如果你把它们放在lib中,require_relative就会工作。”
Rails.application.middleware.insert_after ActionDispatch::ParamsParser, "RequestTimer"
options = { :foo => 'bar' }
Rails.application.middleware.insert_after ActionDispatch::ParamsParser, "SecuredClient", options
class RequestTimer
def initialize(app, params)
@app = app
@params = params
end
end