From 890464f9137fcf8e8f3f28c62a6c818ea37a45ac Mon Sep 17 00:00:00 2001 From: Chris Tsang Date: Sat, 5 Jun 2021 21:36:33 +0800 Subject: [PATCH] Save custom ActiveModel --- examples/sqlx-mysql/src/main.rs | 4 +- examples/sqlx-mysql/src/operation.rs | 37 ++++++++++++++++++- sea-orm-macros/src/derives/active_model.rs | 21 +++++++---- .../src/derives/active_model_behavior.rs | 11 ++++++ sea-orm-macros/src/derives/mod.rs | 2 + sea-orm-macros/src/derives/model.rs | 6 ++- sea-orm-macros/src/lib.rs | 10 +++++ src/entity/prelude.rs | 7 ++-- src/lib.rs | 3 +- src/query/mod.rs | 2 +- 10 files changed, 85 insertions(+), 18 deletions(-) create mode 100644 sea-orm-macros/src/derives/active_model_behavior.rs diff --git a/examples/sqlx-mysql/src/main.rs b/examples/sqlx-mysql/src/main.rs index e180e10ac..fe2c93ea1 100644 --- a/examples/sqlx-mysql/src/main.rs +++ b/examples/sqlx-mysql/src/main.rs @@ -4,15 +4,15 @@ mod example_cake; mod example_cake_filling; mod example_filling; mod example_fruit; -mod select; mod operation; +mod select; use example_cake as cake; use example_cake_filling as cake_filling; use example_filling as filling; use example_fruit as fruit; -use select::*; use operation::*; +use select::*; #[async_std::main] async fn main() { diff --git a/examples/sqlx-mysql/src/operation.rs b/examples/sqlx-mysql/src/operation.rs index e6ef03653..3d400b6bc 100644 --- a/examples/sqlx-mysql/src/operation.rs +++ b/examples/sqlx-mysql/src/operation.rs @@ -2,6 +2,14 @@ use crate::*; use sea_orm::{entity::*, query::*, Database}; pub async fn all_about_operation(db: &Database) -> Result<(), ExecErr> { + save_active_model(db).await?; + + save_custom_active_model(db).await?; + + Ok(()) +} + +pub async fn save_active_model(db: &Database) -> Result<(), ExecErr> { let banana = fruit::ActiveModel { name: Val::set("banana".to_owned()), ..Default::default() @@ -19,4 +27,31 @@ pub async fn all_about_operation(db: &Database) -> Result<(), ExecErr> { println!("Updated: {:?}\n", banana); Ok(()) -} \ No newline at end of file +} + +mod form { + use super::fruit::*; + use sea_orm::entity::prelude::*; + + #[derive( + Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel, DeriveActiveModelBehavior, + )] + pub struct Model { + pub id: i32, + pub name: String, + } +} + +async fn save_custom_active_model(db: &Database) -> Result<(), ExecErr> { + let pineapple = form::ActiveModel { + id: Val::unset(), + name: Val::set("pineapple".to_owned()), + }; + + let pineapple = pineapple.save(db).await?; + + println!(); + println!("Updated: {:?}\n", pineapple); + + Ok(()) +} diff --git a/sea-orm-macros/src/derives/active_model.rs b/sea-orm-macros/src/derives/active_model.rs index 081c39218..76b896397 100644 --- a/sea-orm-macros/src/derives/active_model.rs +++ b/sea-orm-macros/src/derives/active_model.rs @@ -11,7 +11,7 @@ pub fn expand_derive_active_model(ident: Ident, data: Data) -> syn::Result named.named, _ => { return Ok(quote_spanned! { - ident.span() => compile_error!("you can only derive DeriveModel on structs"); + ident.span() => compile_error!("you can only derive DeriveActiveModel on structs"); }) } }; @@ -48,8 +48,8 @@ pub fn expand_derive_active_model(ident: Ident, data: Data) -> syn::Result for ActiveModel { - fn from(m: #ident) -> Self { + impl From<::Model> for ActiveModel { + fn from(m: ::Model) -> Self { Self { #(#field: sea_orm::unchanged_active_value_not_intended_for_public_use(m.#field)),* } @@ -61,31 +61,36 @@ pub fn expand_derive_active_model(ident: Ident, data: Data) -> syn::Result::Column) -> sea_orm::ActiveValue { match c { - #(::Column::#name => std::mem::take(&mut self.#field).into_wrapped_value()),* + #(::Column::#name => std::mem::take(&mut self.#field).into_wrapped_value(),)* + _ => sea_orm::ActiveValue::unset(), } } fn get(&self, c: ::Column) -> sea_orm::ActiveValue { match c { - #(::Column::#name => self.#field.clone().into_wrapped_value()),* + #(::Column::#name => self.#field.clone().into_wrapped_value(),)* + _ => sea_orm::ActiveValue::unset(), } } fn set(&mut self, c: ::Column, v: sea_orm::Value) { match c { - #(::Column::#name => self.#field = sea_orm::ActiveValue::set(v.unwrap())),* + #(::Column::#name => self.#field = sea_orm::ActiveValue::set(v.unwrap()),)* + _ => panic!("This ActiveModel does not have this field"), } } fn unset(&mut self, c: ::Column) { match c { - #(::Column::#name => self.#field = sea_orm::ActiveValue::unset()),* + #(::Column::#name => self.#field = sea_orm::ActiveValue::unset(),)* + _ => {}, } } fn is_unset(&self, c: ::Column) -> bool { match c { - #(::Column::#name => self.#field.is_unset()),* + #(::Column::#name => self.#field.is_unset(),)* + _ => panic!("This ActiveModel does not have this field"), } } diff --git a/sea-orm-macros/src/derives/active_model_behavior.rs b/sea-orm-macros/src/derives/active_model_behavior.rs new file mode 100644 index 000000000..746f57e22 --- /dev/null +++ b/sea-orm-macros/src/derives/active_model_behavior.rs @@ -0,0 +1,11 @@ +use proc_macro2::{Ident, TokenStream}; +use quote::quote; +use syn::Data; + +pub fn expand_derive_active_model_behavior(_ident: Ident, _data: Data) -> syn::Result { + Ok(quote!( + impl sea_orm::ActiveModelBehavior for ActiveModel { + type Entity = Entity; + } + )) +} diff --git a/sea-orm-macros/src/derives/mod.rs b/sea-orm-macros/src/derives/mod.rs index 380c3f9d4..2cf1948ab 100644 --- a/sea-orm-macros/src/derives/mod.rs +++ b/sea-orm-macros/src/derives/mod.rs @@ -1,4 +1,5 @@ mod active_model; +mod active_model_behavior; mod column; mod entity; mod from_query_result; @@ -6,6 +7,7 @@ mod model; mod primary_key; pub use active_model::*; +pub use active_model_behavior::*; pub use column::*; pub use entity::*; pub use from_query_result::*; diff --git a/sea-orm-macros/src/derives/model.rs b/sea-orm-macros/src/derives/model.rs index dd81ce1b1..c304e4c41 100644 --- a/sea-orm-macros/src/derives/model.rs +++ b/sea-orm-macros/src/derives/model.rs @@ -33,13 +33,15 @@ pub fn expand_derive_model(ident: Ident, data: Data) -> syn::Result fn get(&self, c: ::Column) -> sea_orm::Value { match c { - #(::Column::#name => self.#field.clone().into()),* + #(::Column::#name => self.#field.clone().into(),)* + _ => panic!("This Model does not have this field"), } } fn set(&mut self, c: ::Column, v: sea_orm::Value) { match c { - #(::Column::#name => self.#field = v.unwrap()),* + #(::Column::#name => self.#field = v.unwrap(),)* + _ => panic!("This Model does not have this field"), } } } diff --git a/sea-orm-macros/src/lib.rs b/sea-orm-macros/src/lib.rs index 175ba027b..65b8fd151 100644 --- a/sea-orm-macros/src/lib.rs +++ b/sea-orm-macros/src/lib.rs @@ -55,6 +55,16 @@ pub fn derive_active_model(input: TokenStream) -> TokenStream { } } +#[proc_macro_derive(DeriveActiveModelBehavior)] +pub fn derive_active_model_behavior(input: TokenStream) -> TokenStream { + let DeriveInput { ident, data, .. } = parse_macro_input!(input); + + match derives::expand_derive_active_model_behavior(ident, data) { + Ok(ts) => ts.into(), + Err(e) => e.to_compile_error().into(), + } +} + #[proc_macro_derive(FromQueryResult)] pub fn derive_from_query_result(input: TokenStream) -> TokenStream { let DeriveInput { ident, data, .. } = parse_macro_input!(input); diff --git a/src/entity/prelude.rs b/src/entity/prelude.rs index 62d820274..3b18545f6 100644 --- a/src/entity/prelude.rs +++ b/src/entity/prelude.rs @@ -1,6 +1,7 @@ pub use crate::{ ActiveModelBehavior, ActiveModelTrait, ColumnTrait, ColumnType, DeriveActiveModel, - DeriveColumn, DeriveEntity, DeriveModel, DerivePrimaryKey, EntityName, EntityTrait, EnumIter, - Iden, IdenStatic, ModelTrait, PrimaryKeyToColumn, PrimaryKeyTrait, QueryFilter, QueryResult, - Related, RelationDef, RelationTrait, Select, TypeErr, Value, + DeriveActiveModelBehavior, DeriveColumn, DeriveEntity, DeriveModel, DerivePrimaryKey, + EntityName, EntityTrait, EnumIter, Iden, IdenStatic, ModelTrait, PrimaryKeyToColumn, + PrimaryKeyTrait, QueryFilter, QueryResult, Related, RelationDef, RelationTrait, Select, + TypeErr, Value, }; diff --git a/src/lib.rs b/src/lib.rs index cbafdce82..cf31c77bc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -13,7 +13,8 @@ pub use entity::*; pub use query::*; pub use sea_orm_macros::{ - DeriveActiveModel, DeriveColumn, DeriveEntity, DeriveModel, DerivePrimaryKey, FromQueryResult, + DeriveActiveModel, DeriveActiveModelBehavior, DeriveColumn, DeriveEntity, DeriveModel, + DerivePrimaryKey, FromQueryResult, }; pub use sea_query; pub use sea_query::Iden; diff --git a/src/query/mod.rs b/src/query/mod.rs index c4df1b7cb..d04595f66 100644 --- a/src/query/mod.rs +++ b/src/query/mod.rs @@ -20,4 +20,4 @@ pub use select::*; pub use traits::*; pub use update::*; -pub use crate::connector::{QueryErr, ExecErr}; \ No newline at end of file +pub use crate::connector::{ExecErr, QueryErr};