【问题标题】:Altering params in Sinatra before blocks在块之前更改 Sinatra 中的参数
【发布时间】:2019-09-12 06:44:15
【问题描述】:

我正在尝试更改 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

【问题讨论】:

    标签: ruby sinatra


    【解决方案1】:

    路由过滤器先行,它有路由参数:{"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 被保留,因为存在路由参数。

    我不能说这是一个错误还是一个预期的行为,但它至少是一个“如何”,如果不是“为什么”的话。询问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
    

    【讨论】:

    • 谢谢。我知道我可以使用自己的实例变量,但不太理想。这对我来说似乎是一个明确的错误。我会尝试在 Sinatra 回购中报告,如果有任何感兴趣的内容,我会回来报告。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-03-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-11
    • 2020-05-30
    相关资源
    最近更新 更多