Closed paul closed 2 years ago
Values are not passed as keywords to blocks so this is kinda expected. It looks like you'll have to change the application code. Being smart and detecting if a block has keywords is problematic performance-wise I guess.
@flash-gordon After poking around further, I'm not even sure its really possible in Ruby 3. Eg, this simplest possible example doesn't work any more:
>> {foo: 42}.tap { |foo:, **| puts foo }
(irb):1:in `block in <main>': missing keyword: :foo (ArgumentError)
from <internal:kernel>:90:in `tap'
It's possible when you define a method
def success
yield('seq', key: 1, word: 2)
end
The problem is you'll have to know the block's parameters:
def success(&block)
args, kwargs = split_by_parameters(@value, block.parameters)
yield(*args, **kwargs)
end
So it can work but it'll be slow for all users, not only for those with keywords.
Describe the bug
In our application we make heavy use of Transactions, the vast majority of which operate with kwargs and return Hash objects. In several places, we also use keyword block arguments within the match block when calling the transaction (see example).
We're in the process of upgrading to Ruby 3.x, and have run in to an issue with those keyword args. The code works in 2.7.x, and issues no kwarg warnings, but fails with ArgumentError in 3.x. I've distilled it down to a simple example attached below.
I know this can likely be replaced with Ruby 3 pattern matching, but doing so touches a lot of code in our app, and I'm hoping to avoid making too many code changes while doing this upgrade. Would a PR be accepted to fix this, if I were to attempt it?
To Reproduce
Expected behavior
Ruby 2.7.5:
Ruby 3.0.3:
My environment
This seems like its actually an error with dry-matcher and kwargs, because this code results in the same error: