在块之前更改 Sinatra 中的参数

Altering params in Sinatra before blocks

我正在尝试更改 Sinatra 中 before 块中的请求参数。

似乎在使用这种语法时有效:

before do
  @params['global-before'] = 'yes'
end

但是当使用这个语法时,它不起作用:

before '/:id/test' do
  @params['route-before'] = 'yes'
end

这是一个完整的例子:

# test.rb
require 'sinatra'
require 'sinatra/reloader'

set :bind, '0.0.0.0'
set :port, 3000

before do
  @params['global-before'] = 'yes'
end

before '/:id/test' do
  @params['route-before'] = 'yes'
end

get '/' do
  params.to_json
end

get '/:id/test' do
  params.to_json
end

然后运行:

$ ruby test.rb

$ curl localhost:3000
{"global-before":"yes"}

$ curl localhost:3000/123/test
{"global-before":"yes","id":"123"}

我期待看到 params['route-before'] 也被填充。

我试过使用 request.params 而不是 @params 但那根本不起作用。

有人能解释一下吗?

更新:

在 Sinatra 的问题跟踪器中打开了一个 issue

路由过滤器先行,它有路由参数:{"id"=>"123"},所以this发生:

original, @params = @params, @params.merge(params) if params.any?

其中 original 最终为 {}@params 最终为 {"id"=>"123"}。当全局过滤器运行时,没有路由参数,因此 original 保持未分配状态 (nil) 并且 @params 是最初存在的 {}

过滤处理后,在ensure子句中,有this:

@params = original if original

所以全局过滤器会跳过它,因为 originalnil,因为没有路由参数。路由过滤器将 @params 重置为过滤器 运行 之前的任何值,因为保留了 original,因为存在路由参数。

我不能说这是错误还是预期行为,但至少是 "how",如果不是 "why"。询问 Sinatra team(并在此处报告判决结果)可能是有意义的。

tl;dr:如果过滤器的路径模式中有参数,@params 将重置为过滤器前状态。

注意:您可以通过创建自己的实例变量来绕过它:

before '/:id/test' do
  @route_before = 'yes'
end

get '/:id/test' do
  "Did we run route before? #{@route_before}"
end