Skip to main content

ModelForm

Derive Macro ModelForm 

Source
#[derive(ModelForm)]
{
    // Attributes available to this derive:
    #[form]
}
Expand description

Derive a model’s RecordForm struct from the model: the fields a person fills, named and typed as the model declares them.

#[derive(Debug, Clone, toasty::Model, tablo_core::ModelColumns, tablo_core::ModelForm)]
pub struct Book {
    #[key]
    #[auto]
    pub id: uuid::Uuid,
    pub title: String,
    #[form(optional)]
    pub subtitle: String,
    #[default(jiff::Timestamp::now())]
    pub created_at: jiff::Timestamp,
}

// The derive wrote `BookForm { title, subtitle }`, with `BookFormField` and
// `BookFormControls`, as `#[derive(RecordForm)]` would.
let form = BookForm {
    title: "Dune".into(),
    subtitle: String::new(),
};

The form leaves out what no person fills: a key, so an edit never rewrites it, an #[auto], #[update] or #[version] field, a relation, and a TenantId or Option<TenantId> field, which belongs to the resource’s Tenancy. A form key on one of those is a compile error naming the fix. A #[default] field and a #[belongs_to] foreign key are left out unless a form key opts them in, such as #[form(repeat)] on a defaulted list or #[form(relationship = AuthorResource)] on a foreign key. #[form(skip)] leaves out any other field. When the policy allows Create, mounting refuses a non-nullable column left out, such as a key a person picks, unless an overridden create_record names it with create_column.

Each field keeps the model field’s visibility and docs. A field’s #[form(..)] keys are RecordForm’s, as are the form’s checks and defaults. #[form(name = BookEditor)] on the model names the form, BookForm otherwise. A form whose fields differ from the model’s, such as a many-to-many field’s keys, is a #[derive(RecordForm)] struct. Derive the RecordForm struct of a model’s fillable fields; documented on the tablo-core re-export.