Skip to content

Commit

Permalink
feat: enable convert from ActiveModel to Model
Browse files Browse the repository at this point in the history
  • Loading branch information
greenhandatsjtu committed Jul 4, 2022
1 parent b51b1f6 commit 5eaa58f
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 7 deletions.
57 changes: 54 additions & 3 deletions sea-orm-macros/src/derives/active_model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ use syn::{punctuated::Punctuated, token::Comma, Data, DataStruct, Field, Fields,

/// Method to derive an [ActiveModel](sea_orm::ActiveModel)
pub fn expand_derive_active_model(ident: Ident, data: Data) -> syn::Result<TokenStream> {
let fields = match data {
// including ignored fields
let all_fields = match data {
Data::Struct(DataStruct {
fields: Fields::Named(named),
..
Expand All @@ -17,8 +18,15 @@ pub fn expand_derive_active_model(ident: Ident, data: Data) -> syn::Result<Token
})
}
}
.into_iter()
.filter(field_not_ignored);
.into_iter();

let fields = all_fields.clone().filter(field_not_ignored);

let all_field: Vec<Ident> = all_fields
.clone()
.into_iter()
.map(|Field { ident, .. }| format_ident!("{}", ident.unwrap().to_string()))
.collect();

let field: Vec<Ident> = fields
.clone()
Expand Down Expand Up @@ -63,6 +71,27 @@ pub fn expand_derive_active_model(ident: Ident, data: Data) -> syn::Result<Token

let ty: Vec<Type> = fields.into_iter().map(|Field { ty, .. }| ty).collect();

let ignore_attr: Vec<bool> = all_fields
.clone()
.map(|field| !field_not_ignored(&field))
.collect();

let field_value: Vec<TokenStream> = all_field
.iter()
.zip(ignore_attr)
.map(|(field, ignore)| {
if ignore {
quote! {
Default::default()
}
} else {
quote! {
a.#field.into_value().unwrap().unwrap()
}
}
})
.collect();

Ok(quote!(
#[derive(Clone, Debug, PartialEq)]
pub struct ActiveModel {
Expand Down Expand Up @@ -92,6 +121,28 @@ pub fn expand_derive_active_model(ident: Ident, data: Data) -> syn::Result<Token
}
}

#[automatically_derived]
impl std::convert::TryFrom<ActiveModel> for <Entity as EntityTrait>::Model {
type Error = DbErr;
fn try_from(a: ActiveModel) -> Result<Self, DbErr> {
#(if matches!(a.#field, sea_orm::ActiveValue::NotSet) {
return Err(DbErr::Custom(format!("field {} is NotSet", stringify!(#field))));
})*
Ok(
Self {
#(#all_field: #field_value),*
}
)
}
}

#[automatically_derived]
impl sea_orm::TryIntoModel<<Entity as EntityTrait>::Model> for ActiveModel {
fn try_into_model(self) -> Result<<Entity as EntityTrait>::Model, DbErr> {
self.try_into()
}
}

#[automatically_derived]
impl sea_orm::ActiveModelTrait for ActiveModel {
type Entity = Entity;
Expand Down
18 changes: 18 additions & 0 deletions src/entity/model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,3 +115,21 @@ pub trait FromQueryResult: Sized {
SelectorRaw::<SelectModel<Self>>::from_statement(stmt)
}
}

/// A Trait for any type that can be converted into an Model
pub trait TryIntoModel<M>
where
M: ModelTrait,
{
/// Method to call to perform the conversion
fn try_into_model(self) -> Result<M, DbErr>;
}

impl<M> TryIntoModel<M> for M
where
M: ModelTrait,
{
fn try_into_model(self) -> Result<M, DbErr> {
Ok(self)
}
}
8 changes: 4 additions & 4 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -261,9 +261,9 @@
//! 1. [Change Log](https://github.com/SeaQL/sea-orm/tree/master/CHANGELOG.md)
//!
//! ## Who's using SeaORM?
//!
//!
//! The following products are powered by SeaORM:
//!
//!
//! <table>
//! <tbody>
//! <tr>
Expand All @@ -273,9 +273,9 @@
//! </tr>
//! </tbody>
//! </table>
//!
//!
//! SeaORM is the foundation of [StarfishQL](https://github.com/SeaQL/starfish-ql), an experimental graph database and query engine developed by SeaQL.
//!
//!
//! For more projects, see [Built with SeaORM](https://github.com/SeaQL/sea-orm/blob/master/COMMUNITY.md#built-with-seaorm).
//!
//! ## License
Expand Down

0 comments on commit 5eaa58f

Please sign in to comment.