use heck::CamelCase; use proc_macro2::{Ident, TokenStream}; use quote::{format_ident, quote, quote_spanned}; use syn::{Data, DataStruct, Field, Fields, Type}; pub fn expand_derive_active_model(ident: Ident, data: Data) -> syn::Result { let fields = match data { Data::Struct(DataStruct { fields: Fields::Named(named), .. }) => named.named, _ => { return Ok(quote_spanned! { ident.span() => compile_error!("you can only derive DeriveActiveModel on structs"); }) } }; let field: Vec = fields .clone() .into_iter() .map(|Field { ident, .. }| format_ident!("{}", ident.unwrap().to_string())) .collect(); let name: Vec = fields .clone() .into_iter() .map(|Field { ident, .. }| format_ident!("{}", ident.unwrap().to_string().to_camel_case())) .collect(); let ty: Vec = fields.into_iter().map(|Field { ty, .. }| ty).collect(); Ok(quote!( #[derive(Clone, Debug, PartialEq)] pub struct ActiveModel { #(pub #field: sea_orm::ActiveValue<#ty>),* } impl std::default::Default for ActiveModel { fn default() -> Self { ::new() } } impl std::convert::From<::Model> for ActiveModel { fn from(m: ::Model) -> Self { Self { #(#field: sea_orm::unchanged_active_value_not_intended_for_public_use(m.#field)),* } } } impl sea_orm::IntoActiveModel for ::Model { fn into_active_model(self) -> ActiveModel { self.into() } } impl sea_orm::ActiveModelTrait for ActiveModel { type Entity = Entity; fn take(&mut self, c: ::Column) -> sea_orm::ActiveValue { match c { #(::Column::#name => { let mut value = sea_orm::ActiveValue::unset(); std::mem::swap(&mut value, &mut self.#field); value.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(),)* _ => 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()),)* _ => panic!("This ActiveModel does not have this field"), } } fn unset(&mut self, c: ::Column) { match c { #(::Column::#name => self.#field = sea_orm::ActiveValue::unset(),)* _ => {}, } } fn is_unset(&self, c: ::Column) -> bool { match c { #(::Column::#name => self.#field.is_unset(),)* _ => panic!("This ActiveModel does not have this field"), } } fn default() -> Self { Self { #(#field: sea_orm::ActiveValue::unset()),* } } } )) }