-
Notifications
You must be signed in to change notification settings - Fork 41
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support cross-field validation #98
Conversation
hey @lnhrdt, thanks! For maintainership, please reply in: #38 bikeshedding, what about
API would become: Validation<Register> {
Register::password {
addConstraint("cannot equal email") { it != this@Validation.subject.email }
}
}
// or if user prefers
Validation<Register> {
val register = subject
Register::password {
addConstraint("cannot equal email") { it != register.email }
}
} |
Reading this: #29 (comment) I like this suggestion a lot. we could pass a context object to the validation builder, the first field of which could be subject. API would become: Validation<Register> { (register) ->
Register::password {
addConstraint("cannot equal email") { it != register.email }
}
}
// In ValidationBuilder
data class Context(val subject: T) we can extend the context later if we want, it will not break backwards compatibility because the above snippet will keep working if a field is added. |
Thank you for chiming in with your thoughts @dhoepelman!
I agree this is most compelling. I refactored my PR to implement that design. I've tried to make minimal changes to accomplish the design. Here's the latest. I found that moving the Context class and its management from ValidationBuilder to Validation fit this design better, as Validation has access to In the most recent implementation, I've enhanced the validate function by applying wrapping and delegation. This allows the function to capture the subject, which is then used to construct the context object. konform/src/commonMain/kotlin/io/konform/validation/Validation.kt Lines 7 to 22 in 42b7cab
In a validator without destructuring, the implementation works. This test passes: konform/src/commonTest/kotlin/io/konform/validation/ValidationBuilderTest.kt Lines 118 to 129 in 42b7cab
However when I add destructuring to a validator's implementation I run into a problem. The subject is evaluated too soon in the Validation class's lifecycle (i.e. before subject has been provided by invoking validate) and the exception in Context is thrown. This test fails: konform/src/commonTest/kotlin/io/konform/validation/ValidationBuilderTest.kt Lines 131 to 142 in 42b7cab
I'm struggling to find a way to implement this in a way that doesn't more fundamentally change the Validation interface, implementations, and lifecycle. So I thought I'd check in here. Do you see any possible improvements to what I've started? |
@lnhrdt can you rebase or merge properly? Bit hard to review now |
- Moving Context from ValidationBuilder to Validation - This commit includes a failing test, destructuring doesn't work yet.
96b7ea2
to
42b7cab
Compare
@dhoepelman good catch! I just cleaned up the commit history with a proper rebase. |
I took a look at this and the unfortunate thing is that this is using a var, and not in a thread safe way, so this will lead to race conditions and bugs. Here is a test that should specifically surface these kinds of problems.
This might be worth it, especially if we can find a way to implement this in a backwards compatible way by keeping the old API working. It's a tricky problem to solve, because the builder will not normally have the subject available, so we do need some kind of "getter", but also make sure that the builder doesn't actually have the subject available yet until validation time (throws exception if you try) I will take some time to look at this problem myself, but not sure about when I will have time. |
Going to go in a different direction, probably building on #65, so closing this. Thanks for the inspiration! |
After reflecting on my comment in #29 I decided to explore contributing a pull request to support cross-field validation.
So far I have only added a failing test that suggests a possible API to add support. I am seeking feedback from the maintainers:
@nlochschmidt and @dhoepelman I would love to hear from you.
Lastly, if I get familiar enough with this library through this process I would be interested in helping maintain it–I'm a big fan of Konform. <3