Open kamilglod opened 10 months ago
I can't find any confirmation in README that it's supported and recommended way of accessing struct siblings.
The self.field
and ctx.field
syntax is definitely part of the public API, and there's a mention of it in the top-level docs and README here, but there's no usage of self
in the example, which should fixed.
For equality between two fields, we could add an equals
rule that would use PartialEq
:
#[derive(garde::Validate)]
struct User {
#[garde(length(min=1, max=255))]
password: String,
#[garde(equals(self.password))]
password2: String,
}
Adding equals()
sounds good but it would solve only one use case, it would be good to have more general solution. Using closure with access to self
sounds good, but for shared functions we would need to do somehing like:
#[derive(garde::Validate)]
pub struct User {
#[garde(length(min = 1, max = 255))]
password: String,
#[garde(length(min = 1, max = 255))]
#[garde(custom(|value: &String, _ctx: &()| {
some_shared_validator(value, self.repeat_password)
}))]
repeat_password: String,
}
fn some_shared_validator(val: &String, other: &String) {}
instead of
#[derive(garde::Validate)]
pub struct User {
#[garde(length(min = 1, max = 255))]
password: String,
#[garde(length(min = 1, max = 255))]
#[garde(custom(some_shared_validator, other = self.repeat_password))]
repeat_password: String,
}
fn some_shared_validator(val: &String, other: &String, _ctx: &()) {}
The general solution is custom
. It doesn't always result in the most aesthetically pleasing solution, but you can use it to do pretty much anything you can think of. It accepts any expression that evaluates to impl FnOnce(&T, &Ctx) -> garde::Result
, so you can use a higher-order function, or a macro that evaluates to a closure:
#[derive(garde::Validate)]
struct User {
#[garde(length(min = 1, max = 255))]
password: String,
#[garde(custom(some_shared_validator(&self.password2)))]
password2: String,
}
fn some_shared_validator(other: &str) -> impl FnOnce(&str, &()) -> garde::Result {
|value, ctx| todo!()
}
higher-order function works very well, I think this issue might be close but some extra example in README will be very welcomed.
I added an example to the README in https://github.com/jprochazk/garde/commit/5b80e50203dcc91de8ffc2608e91813878107e57, but I'm keeping this open for an equals
rule.
Perhaps I'm misunderstanding but is the equals
described here the same as matches
added in #110?
It's quite common to have a logic in validation where we want to validate field based on values in other fields, or ensure that all fields are either filled or empty.
field_name
to theValidationError
). There would be super helpful to have an access togarde::Report
inside custom validator. We can usevalidate_into
but it's not working with#[derive(garde::Validate)]
impl garde::Validate for User { fn validate_into( &self, ctx: &Self::Context, mut parent: &mut dyn FnMut() -> garde::Path, report: &mut garde::Report ) { if self.password != self.repeat_password { let mut path = parent().join("repeate_password"); report.append(path, garde::Error::new("passwords are not equal")); } } }
self
:Option 3 looks like the best solution but I can't find any confirmation in README that it's supported and recommended way of accessing struct siblings.