首页 > 解决方案 > 从 Ruby 2.7 升级到 3.0 时出现 ArgumentError - 与位置参数和关键字参数的分离有关?

问题描述

我正在尝试将 gem 从 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 禁用/启用行,以防万一它们很重要。

工厂以这种方式调用类:

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 的情况下成功创建。

我心想,“很酷,我只需将 Factory 的 Class 调用更新为这种新格式并重新运行测试即可。” 这样做之后,我仍然得到与上面相同的 ArgumentError。

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

从 Ruby 2.7 更新到 Ruby 3.0 后,我还查看了有关 ArgumentError 的 Stack Overflow 问题,并试图了解如何使用第一个答案的第一部分来帮助我解决问题(忽略与 PR 相关的更新)。

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

标签: rubyruby-2.7ruby-3

解决方案


当你这样做时……</p>

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

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

如果你改为这样称呼它……</p>

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

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

这被称为“双 splat”,是针对您的用例引入的,将哈希转换为关键字参数。


推荐阅读