Open vlad-pisanov opened 1 month ago
I don't even know how it handles positional optional arguments I see nothing from https://egonschiele.github.io/contracts.ruby/ Have you used contract on methods with positional optional arguments only?
It is indeed not documented, but it works as expected when only positional arguments are used:
class C
include Contracts
Contract String, String => Any
def goo(a = 'a', b = 'b')
p [a, b]
end
end
c = C.new
c.goo # Works ✔️
c.goo('a') # Works ✔️
c.goo('a', 'b') # Works ✔️
The issue seems to be in KeywordArgs
, because if I replace the original example with Any
, everything works again:
class C
include Contracts
Contract String, Any => Any
def hoo(a = 'a', b: 'b')
p [a, b]
end
end
c = C.new
c.hoo('a', b: 'b') # Works ✔️
c.hoo('a') # Works ✔️
c.hoo(b: 'b') # Works ✔️
c.hoo # Works ✔️
I think it's a deeper issue of lacking a contract for optional positional argument From my limited understand it works like this
It's fine for methods with optional arguments only coz it works like: Contracts declared: contract_at_pos_1, contract_at_pos_2 When some arguments not passed, it checks like: arg1 => contract_at_pos_1, no arg2 = no check
But if optional positional argument is mixed with keyword arguments Contracts declared: contract_at_pos_1, contract_keyword_args It checks like: keyword_args => contract_at_pos_1
I am guessing from https://github.com/egonSchiele/contracts.ruby/blob/v0.17/lib/contracts/call_with.rb#L51-L81
Please check https://github.com/egonSchiele/contracts.ruby/pull/305 and see if you want to add more examples to ensure I don't break anything Use it in your app for a while to ensure nothing breaks
I won't merge https://github.com/egonSchiele/contracts.ruby/pull/305 until some has tested it~
Thanks for the patch! I'll test it later this week.
I'm having trouble defining a contract for a method that takes two optional arguments -- a positional one and a keyword one. Consider:
The stack trace is
It seems Contracts wants me to provide the positional argument even if a default is specified in the method signature? 🤔