pub enum WriteError<K = String> {
Refused(FieldErrors<K>),
Failed(Error),
}Expand description
Why a record fn or an action’s run wrote nothing: a refusal the form renders, or a failure.
Either way the handler rolls the transaction back, so whatever the fn wrote before it returned is undone.
Refusedrenders the form again with status 200, each error under the control of the field it names, as avalidate_recorderror does. A record fn keys its errors by the record form’s field enum, an action’s run by its input’s form keys.Failedanswers as a failed write does: a record fn’s collision on a unique index renders under the field’s control, a save another save overtook renders the stale form, and any other error flashes the failure toast and answers with the error.
A refusal is the answer to a rule that reads the database: a stock level, a quota, a uniqueness no index models. A rule the write itself enforces holds against concurrent writes: an update filtered on the stock it needs that matches no row refuses the very write it would have made.
? turns any error a topcoat::Error takes into Failed, and a
FieldErrors into Refused:
use tablo_core::{FieldErrors, RecordForm, Resource, WriteError, write_create};
use topcoat::context::Cx;
impl Resource for OrderResource {
type Model = Order;
type Form = OrderForm;
async fn create_record(
cx: &Cx,
form: OrderForm,
ex: &mut dyn toasty::Executor,
) -> Result<Order, WriteError<OrderFormField>> {
let stock = Stock::filter_by_sku(&form.sku)
.first()
.exec(&mut *ex)
.await?;
if stock.is_none_or(|stock| stock.level < form.quantity) {
let mut errors = FieldErrors::new();
errors.add(OrderFormField::Quantity, "Not enough in stock");
return Err(errors.into());
}
Ok(write_create::<Self>(cx, form, ex).await?)
}
}Variants§
Refused(FieldErrors<K>)
The submission cannot stand: render the form again with these errors.
Failed(Error)
The write failed: answer with this error and the failure toast.
Implementations§
Trait Implementations§
Source§impl<K: Debug> Debug for WriteError<K>
impl<K: Debug> Debug for WriteError<K>
Source§impl<K> From<FieldErrors<K>> for WriteError<K>
impl<K> From<FieldErrors<K>> for WriteError<K>
Source§fn from(errors: FieldErrors<K>) -> Self
fn from(errors: FieldErrors<K>) -> Self
Converts to this type from the input type.
Auto Trait Implementations§
impl<K = String> !RefUnwindSafe for WriteError<K>
impl<K = String> !UnwindSafe for WriteError<K>
impl<K> Freeze for WriteError<K>where
FieldErrors<K>: Freeze,
impl<K> Send for WriteError<K>where
FieldErrors<K>: Send,
impl<K> Sync for WriteError<K>where
FieldErrors<K>: Sync,
impl<K> Unpin for WriteError<K>where
FieldErrors<K>: Unpin,
impl<K> UnsafeUnpin for WriteError<K>where
FieldErrors<K>: UnsafeUnpin,
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more