Проблема с define_method в Ruby 3.0
Я работаю над обновлением Ruby 2.7 до 3.0 и столкнулся с проблемой с изменением аргументов ключевого слова.
Раньше мы для некоторых целей использовали в нашем коде define_method. Однако с изменением аргументов ключевого слова он больше не может правильно обрабатывать массив аргументов.
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)
Это поднимет
wrong number of arguments (given 1, expected 0) (ArgumentError)
. И раньше это работало в Ruby 2.7. Что мы можем сделать, чтобы *args снова заработал?
1 ответ
Пытаться
define_method(:test) do |*args, **kwords, &block|
old_method.bind(self).call(*args, **kwords, &block)
end
Ruby меняет обработку аргументов метода, которые выдают предупреждение об устаревании в
2.7
. Произошло непредвиденное поведение, включая ключевые слова в
*args
множество. Это должно было быть сделано с использованием хеша, и должно быть больше различий между хеш-аргументом и ключевыми словами. Так в рубине
3.x
вам нужно записать произвольную коллекцию ключевых слов в двойной знак, потому что они не могут быть включены в аргумент splat.
В основном мое понимание шаткое, но я читаю это как явный пример в объяснении измененных аргументов в примечаниях к выпуску для ruby
3.0
.