Reputation: 69
I'm working on an upgrade from Ruby 2.7 to 3.0 and faced an issue with the keyword arguments change.
Previously we used define_method in our code for some purposes. However, with the keyword arguments change, it can no longer handle an array of arguments properly anymore.
class Foo
def test(a: 1, b: 2)
puts a
puts b
end
old_method = instance_method(:test)
define_method(:test) do |*args, &block|
old_method.bind(self).call(*args, &block)
end
end
Foo.new.test(a: 1)
This will raise wrong number of arguments (given 1, expected 0) (ArgumentError)
. And it previously worked in Ruby 2.7. Is there anything we can do to get the *args to work again?
Upvotes: 2
Views: 897
Reputation: 10099
Try
define_method(:test) do |*args, **kwords, &block|
old_method.bind(self).call(*args, **kwords, &block)
end
Ruby 3.0
is changing the handling of method arguments which give a deprecation warning in 2.7
. There is some unexpected behavior including a keywords in a *args
array. This had to be done using a hash and there needs to be more of a distinction between a hash argument and keywords. So in ruby 3.x
you need to capture an arbitrary collection of keywords in a double splat because they cannot be included in the splat argument.
Mostly my understanding is shaky but I read this as an explicit example in the explanation of the changed to the arguments in the release notes for ruby 3.0
.
Upvotes: 5