You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I'm working on a simple framework which has a feature where the user can choose to send the changes to a form. This works by some javascript code keeping a cached copy of the original form fields, and once the user clicks submit the js will generate a FormData which contains the form fields that have changed. The Rocket application encapsulates the potentially-changed types in an Option<>:
(The ones that are unchanged will be received as None).
Unfortunately there's another feature where the developer can choose to mark certain fields as "null if empty". If the backend database has a column which is nullable, and it doesn't make sense for a string to be empty, then it can be omitted so that it can be received as an Option, and the backend can set the column to NULL (if the field is None).
So it should be fairly obvious that these two features can clash: How would one signal that a field has changedand that its new value is NULL/None.
Since I control the serialization I can easily solve this, and there are two obvious solutions:
The serializer adds a separate (implicit) field, for instance for a name field there's an implicit name-changed boolean. Or one could instead use a name-isnull. Anyway, the point is that the extra field is added to the FromForm-derived struct in the Rocket application and the database functions use these extra fields to determine if the field has changed and/or is null.
The value string is given a prefix/keyword to indicate if it has a value or is null: value:Frank Foobar/null. The field's Option would be used to indicate whether a change has occurred or not.
These works, however I'd like something more ergonomic. I'd like the application to not have to be aware of the extra field (as in the first solution) or have to parse the field (as in the second version).
.. where SomeType can be used to signal all the possible states. One solution would be Option<Option<String>> where the outer Option signals whether it changed or not, and the inner whether it is NULL or not. Another solution would be an enum which can signal all the various possible states. But I realize these would be "unnatural" at best, and out-of-spec at worst. But these examples are more to illustrate a what I would like to achieve within the bounds of what's reasonable for Rocket to support.
I assume I could implement these features by manually implementing FromFormField for a custom type, but here's where I believe it gets a little hairy: I want to be able to use this feature generically and support field validators:
pub struct AccName(pub String);
impl<'v> FromFormField<'v> for AccName {
fn from_value(field: ValueField<'v>) -> form::Result<'v, Self> {
let s = field.value;
if !validate_name(&s) {
let error = form::Error::validation("Account name has bad form");
Err(error)?
} else {
Ok(AccName(s.to_string()))
}
}
}
#[derive(FromForm)]
struct UpdateRecord {
id: i64,
name: Magic<AccName>,
}
Where Magic would be the wrapper which can be used to signal if the field was not present at all, or it didn't change or it did change and the value was properly validated (AccName is validated).
How far can one get with what Rocket has in 0.5.0 to accomplish this? And are there any things in the pipeline for the (distant) future which can help implementing such patterns?
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
-
I'm working on a simple framework which has a feature where the user can choose to send the changes to a form. This works by some javascript code keeping a cached copy of the original form fields, and once the user clicks submit the js will generate a
FormData
which contains the form fields that have changed. The Rocket application encapsulates the potentially-changed types in anOption<>
:(The ones that are unchanged will be received as
None
).Unfortunately there's another feature where the developer can choose to mark certain fields as "null if empty". If the backend database has a column which is nullable, and it doesn't make sense for a string to be empty, then it can be omitted so that it can be received as an
Option
, and the backend can set the column toNULL
(if the field isNone
).So it should be fairly obvious that these two features can clash: How would one signal that a field has changed and that its new value is
NULL
/None
.Since I control the serialization I can easily solve this, and there are two obvious solutions:
name
field there's an implicitname-changed
boolean. Or one could instead use aname-isnull
. Anyway, the point is that the extra field is added to theFromForm
-derived struct in the Rocket application and the database functions use these extra fields to determine if the field has changed and/or is null.value
or isnull
:value:Frank Foobar
/null
. The field'sOption
would be used to indicate whether a change has occurred or not.These works, however I'd like something more ergonomic. I'd like the application to not have to be aware of the extra field (as in the first solution) or have to parse the field (as in the second version).
I'd like to be able to do something like this:
.. where
SomeType
can be used to signal all the possible states. One solution would beOption<Option<String>>
where the outerOption
signals whether it changed or not, and the inner whether it isNULL
or not. Another solution would be an enum which can signal all the various possible states. But I realize these would be "unnatural" at best, and out-of-spec at worst. But these examples are more to illustrate a what I would like to achieve within the bounds of what's reasonable for Rocket to support.I assume I could implement these features by manually implementing
FromFormField
for a custom type, but here's where I believe it gets a little hairy: I want to be able to use this feature generically and support field validators:Where
Magic
would be the wrapper which can be used to signal if the field was not present at all, or it didn't change or it did change and the value was properly validated (AccName
is validated).How far can one get with what Rocket has in 0.5.0 to accomplish this? And are there any things in the pipeline for the (distant) future which can help implementing such patterns?
Beta Was this translation helpful? Give feedback.
All reactions