diff --git a/sea-orm-macros/src/derives/model_ex.rs b/sea-orm-macros/src/derives/model_ex.rs index b181a9ae9..fe6585046 100644 --- a/sea-orm-macros/src/derives/model_ex.rs +++ b/sea-orm-macros/src/derives/model_ex.rs @@ -50,13 +50,19 @@ pub fn expand_sea_orm_model(input: ItemStruct, compact: bool) -> syn::Result" .replace(' ', ""); // Remove spaces - + if !(field_type.starts_with("Option<") + || field_type.starts_with("HasMany<") + || field_type.starts_with("HasOne<")) + { + required_model_fields.push(field.clone()); + } if is_compound_field(&field_type) { let entity_path = extract_compound_entity(&field_type); if field_type.starts_with("Option<") || field_type.starts_with("HasOne<") { @@ -69,6 +75,31 @@ pub fn expand_sea_orm_model(input: ItemStruct, compact: bool) -> syn::Result>(); + + let required_field_names = required_model_fields + .iter() + .map(|item| &item.ident) + .collect::>(); + let required_field_types = required_model_fields + .iter() + .map(|item| &item.ty) + .collect::>(); + let from_required_fields = quote! { + impl #model_ex { + pub fn model_from_required(#(#required_field_names: #required_field_types),*) -> #model { + #model { + #(#required_field_names),*, + #(#non_required_model_field_names : None),* + } + } + } + }; + Ok(quote! { #(#model_attrs)* #[sea_orm(model_ex)] @@ -79,6 +110,7 @@ pub fn expand_sea_orm_model(input: ItemStruct, compact: bool) -> syn::Result Ident { #[cfg(test)] mod test { use super::format_tuple; + use crate::{DbErr, entity::*, tests_cfg::*}; + use pretty_assertions::assert_eq; #[test] fn test_format_tuple() { @@ -799,4 +833,16 @@ mod test { "(super::Column::A, super::Column::B)" ); } + + #[test] + fn test_new_from_required() { + assert_eq!( + fruit::ModelEx::model_from_required(1, "Example Fruit"), + fruit::Model { + id: 1, + name: "Example Fruit", + cake_id: None, + } + ); + } }