【问题标题】:Sinatra: params hash cannot be mergedSinatra:无法合并参数哈希
【发布时间】:2016-06-17 15:15:53
【问题描述】:

我想将哈希与默认参数和请求中给出的实际参数合并。当我调用这个看似无辜的脚本时:

#!/usr/bin/env ruby

require 'sinatra'

get '/' do
        defaults = { 'p1' => 'default1', 'p2' => 'default2' }
        # params = request.params
        params = defaults.merge(params)
        params
end

curl http://localhost:4567?p0=request 然后它崩溃了

Listening on localhost:4567, CTRL+C to stop
2016-06-17 11:10:34 - TypeError - no implicit conversion of nil into Hash:
        sinatrabug:8:in `merge'
        sinatrabug:8:in `block in <main>'

当我直接访问机架request.params 时,它可以工作。我查看了 Sinatra 的来源,但无法弄清楚。

所以我有一个解决我实际问题的方法。但我不知道为什么它有效。

我的问题是:为什么我可以将param 分配给参数,为什么类Hash 但在defaults.merge params 中却抛出异常?

有什么想法吗?

【问题讨论】:

  • 你能发布params.inspect的输出吗?也可以尝试附加.to_h。有时它有效!
  • params.inspect?returns: NoMethodError - undefined method inspect?'对于 {}:Hash:. I already tried the .to_h` 方法无效。
  • @SteffenRoller 没有问号,应该是params.inspect
  • params.inspect 返回一个空哈希 {}

标签: ruby sinatra


【解决方案1】:

这是由 Ruby 处理同名的局部变量和 setter 方法(即以 = 结尾的方法)的方式引起的。当 Ruby 到达终点时

params = defaults.merge(params)

它假定您要创建一个名为params 的新局部变量,而不是使用该方法。这个变量的初始值为nil,这就是merge方法看到的值。

如果要引用该方法,则需要将其引用为self.params=。这适用于任何具有这种方法的对象,而不仅仅是 Sinatra。

为了完全避免这种混淆,更好的解决方案可能是使用不同的名称。比如:

get '/' do
  defaults = { 'p1' => 'default1', 'p2' => 'default2' }
  normalized_params = defaults.merge(params)
  normalized_params.inspect
end

【讨论】:

    【解决方案2】:

    您的代码抛出错误,因为当您调用 defaults.merge(params) 时,paramsnil。我假设您正在尝试将 defaultsrequest.params 合并,这应该包含来自您的 GET 的参数。

    改变这一行

    params = defaults.merge(params)
    

    到这里

    params = defaults.merge(request.params)
    

    【讨论】:

    • 是的,日志清楚地表明它是nil。因此我切换到reuquest.params。这是我的问题脚本中的第 7 行。我想有人可以告诉我为什么。因为我可以将params 分配给一个变量并打印不是nil 的变量。我想在幕后发生了一些事情,我希望这里有人能解释一下。
    • 是的,我很困惑。如果您在 RHS 上引用params而不调用它的方法,它会解析为request.params。但是,如果您确实在 RHS 上进行了方法调用,那么 Ruby 会假定 paramsnil。几乎看起来像是 Ruby 中的一个错误......
    • 我怀疑不是 Ruby,可能是 Sinatra 或 Rack。
    【解决方案3】:

    我在机架 gem 中找到了这个

    http://www.rubydoc.info/gems/rack/Rack/Request#params-instance_method

    您似乎可以通过params 方法检索 GET 和 POST 数据,但您不能在其中写入。您必须改用update_paramdelete_param

    【讨论】:

    • 这不是真的,因为如果你这样做params = defaults.merge(request.params) 它工作得很好。
    猜你喜欢
    • 2014-02-04
    • 2015-08-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-24
    • 2014-04-16
    • 1970-01-01
    相关资源
    最近更新 更多