Open aleksandra-stolyar opened 4 years ago
Just ran into these same issues with included_in?
and format?
:format?
predicate.About the other two, the issue is that they are related to predicates expecting an array (or range) as argument. It hasn't straightforward solution. Macro argument(s) are forwarded to the predicate method, and we don't have any way to tell whether it expects an array or an unitary item. I see three options:
rule('hogwarts_house.head').validate(size?: [1..255])
rule('hogwarts_house.common_room.location').validate(included_in?: [['tower', 'underground']])
Manually keep record of what predicates expect what.
Modify dry-logic
so that the predicates with array or range arguments also work with splat arguments.
@waiting-for-dev that's OK, it's always worked like that, going back to dry-validation 0.x
. We gotta make sure to document it properly.
@waiting-for-dev ...no wait, sorry - it did not work like that in dry-validation 0.x
! dooh. OK this needs to be investigated because I can't say why it's not working as expected in case of predicate extension :(
Currently, a predicate can be of three kinds:
#method(input)
, as in #empty?([1, 2])
#method(value, input)
, as in #gt?(1, 2)
#method(list_value, input)
, as in #included_in?([1, 2], 1)
The last two are problematic when used with import_predicates_as_macros
extension. Macro arguments are always collected as an array:
rule(:age).validate(gt: 18) # => `macro.args` is `[18]`
rule(:age).validate(included_in: [18, 21]) # => `macro.args` is `[18, 21]`
In the #included_in?
example, of course the user should provide a nested array [[18, 21]]
, because they want to provide an array argument and not two arguments. But as the predicate method is "hidden", there is the concern whether it means expecting too much from them.
As ruby is a dynamically typed language, there is no way to know whether the expected argument is an array or not. Currently, when arguments are dispatched they are splatted, so when you provide an array like in included_in
it results in a wrong number of arguments error.
In the case of #size?
the user is in fact providing what the predicate method expects, but dry-validation
coerces arguments with Array()
so the information is lost.
Maybe we should:
Array()
. Just create a singleton array when provided macro arguments returns false with #is_a?(Array)
.dry-logic
to accept splatted arguments, but I don't like moving the complexity to the fundamental piece...Don't coerce with Array()
I bet that is the solution we're looking for
The referenced PR should fix the issue here with #size?
predicate usage with a range.
About #included_in?
, the predicate expects an array so the correct way to specify it is included_in?: [[18, 21]]
. Saying [18, 21]
would mean that the predicate expected two arguments. I understand this may seem confusing at first sight. As I said, an option would be modifying dry-logic
to also accept splatted arguments, but I don't like it very much.
For
included_in?
andsize?
passing an array of integers/strings not working but it works when just one value passed or with predicates which do not require arrays)included_in?
size?
This predicate is just returning error.
format?