【问题标题】:Ruby 2.6.3 - 'warn' a hash with a symbol as key produces ArgumentErrorRuby 2.6.3 - 以符号为键的“警告”哈希会产生 ArgumentError
【发布时间】:2019-12-25 04:49:51
【问题描述】:

使用 Ruby 2.6.3,我遇到了一个错误,当我尝试“警告”一个至少有一个键作为符号的哈希时,会引发 ArgumentError。如果我尝试“放置”相同的哈希,则不会出现错误并且哈希会正常打印。

 >> h = {:one => 1}
  => {:one=>1}

 >> puts h
 {:one=>1}
  => nil

 >> warn h
  Traceback (most recent call last):
    5: from /Users/rishi/.rvm/rubies/ruby-2.6.3/bin/irb:23:in `<main>'
    4: from /Users/rishi/.rvm/rubies/ruby-2.6.3/bin/irb:23:in `load'
    3: from /Users/rishi/.rvm/rubies/ruby-2.6.3/lib/ruby/gems/2.6.0/gems/irb-1.0.0/exe/irb:11:in `<top (required)>'
    2: from (irb):48
    1: from /Users/rishi/.rvm/rubies/ruby-2.6.3/lib/ruby/site_ruby/2.6.0/rubygems/core_ext/kernel_warn.rb:15:in `block in <module:Kernel>' 
  ArgumentError (unknown keyword: one) 

似乎在我的 kernel_warn.rb 的第 15 行抛出错误:

module_function define_method(:warn) {|*messages, uplevel: nil|
   ...

谁能建议如何解决?

【问题讨论】:

    标签: ruby hash symbols


    【解决方案1】:

    因为永远一样,Ruby 允许在方法调用中将大括号放在 hash-as-last-argument 周围,以允许类似关键字的参数。这允许 Rails 做例如

    link_to "Delete", @item, method: "delete"
    

    解释为

    link_to("Delete", @item, { method: "delete" })
    

    然后 Ruby 获得了对关键字参数的支持,但他们不得不被入侵,以一种仍然可以使所有旧代码运行的方式。因此,关键字参数被视为这个参数最终散列。你的问题是:如果签名中有关键字参数,那么关键字参数会严格检查签名;你不能有额外的关键字参数,就像你不能有额外的位置参数一样。请记住,这些都是等价的:

    warn h
    warn({ one: 1 })
    warn(one: 1)
    

    Ruby 在签名中看到一个位置参数,并查看传递的最后一个参数是否是散列。是的,因此它假定它需要与签名进行比较的是关键字参数哈希 - 而one: 不是有效的关键字。

    怎么办?确保哈希不是最后一个参数。在微不足道的层面上,您可以这样做:

    warn h, "was my hash"
    # {:one=>1}
    # was my hash
    

    您可以做的另一件事是记住warn 需要一个字符串;如果它没有得到一个,它将对参数进行字符串化。所以你可以先发制人:

    warn h.to_s
    # {:one=>1}
    

    tl;dr:Ruby 关键字参数很奇怪。

    【讨论】:

    • 谢谢!似乎to_s 解决方案可能是最佳实践。
    猜你喜欢
    • 2011-07-01
    • 2012-01-01
    • 2014-05-23
    • 2011-11-02
    • 1970-01-01
    • 2014-02-22
    • 2021-02-02
    • 2011-01-16
    • 1970-01-01
    相关资源
    最近更新 更多