从 Ruby 2.7 升级到 3.0 时出现 ArgumentError - 与位置参数和关键字参数的分离有关吗?

问题描述

我正在尝试将 gems 从 ruby​​ 2.7.0 升级到 3.0.0。我已经尝试阅读并提前计划我遇到的障碍,例如 Separation of positional and keyword arguments

我已经顺利更新了两个 gem,但是我已经开始升级第三个,并且在使用 RSpec 测试 3.0 更新时遇到了以下错误

ArgumentError:
        wrong number of arguments (given 1,expected 0; required keyword: children)

我正在尝试通过工厂实例化一个类。堆栈跟踪指向此函数的参数:

      # rubocop:disable Style/KeywordParametersOrder
      def initialize(parent_obj: nil,children:,**attributes)
        @attributes = attributes
        @parent = parent_obj
        @children_json = children
      end
      # rubocop:enable Style/KeywordParametersOrder

虽然我不认为这很重要,但我已经包含了 rubocop dis/enable 行,以防万一它们很重要。

工厂以这种方式调用类:

data = {:some_data=>"foo",:some_name=>"bar",:children=>[]}
Long::Class::Name.new(data)

现在,当我窥探 data 和 Long::Class::Name.new(data) 之间的代码并实例化我自己的 Long::Class::Name 时,如下所示:

Long::Class::Name.new(children: children,attributes: data)

它导致成功创建而没有 ArgumentError。

我对自己说,“太棒了,我只是将工厂的类调用更新为这种新格式并重新运行测试。”执行此操作后,我仍然收到与上述相同的 ArgumentError。

相信这是一个位置/关键字参数的问题,就像我上面链接的那样,但我无法看到如何纠正这个问题。除了上面的链接,我还研究了 Ruby 3 Keyword ArgumentsHash and Keyword Coercion and Ruby 3 Changes。我相信我正面临最后一个链接的“不可预见的后果”部分。

我还查看了有关 ArgumentError after updating from Ruby 2.7 to Ruby 3.0 的 Stack Overflow 问题,并试图了解如何使用第一个答案的第一部分来帮助我解决问题(不考虑与 PR 相关的更新)。

关于如何消除或解决错误的任何想法?我有很多 gem 需要更新,我相信这不会是我最后一次看到这个错误。任何帮助将不胜感激。如果需要更多信息,请告诉我。

解决方法

当你这样做时......

data = {:some_data=>"foo",:some_name=>"bar",:children=>[]}
Long::Class::Name.new(data)

...您正在使用一个位置参数(一个包含键 :some_data:some_name:children 的哈希)并且没有关键字参数调用该方法。

如果你改为这样称呼它......

Long::Class::Name.new(**data)

...你会在没有位置参数和三个关键字参数的情况下调用它。

这被称为“double splat”,专门针对您的用例引入,将散列转换为关键字参数。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...