Merge pull request #166 from SeaQL/model-ignore-attribute

Model ignore attributes
This commit is contained in:
Chris Tsang 2021-09-17 17:20:42 +08:00 committed by GitHub
commit 5509048550
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 92 additions and 8 deletions

View File

@ -1,3 +1,4 @@
use crate::util::field_not_ignored;
use heck::CamelCase;
use proc_macro2::{Ident, TokenStream};
use quote::{format_ident, quote, quote_spanned};
@ -14,7 +15,9 @@ pub fn expand_derive_active_model(ident: Ident, data: Data) -> syn::Result<Token
ident.span() => compile_error!("you can only derive DeriveActiveModel on structs");
})
}
};
}
.into_iter()
.filter(field_not_ignored);
let field: Vec<Ident> = fields
.clone()

View File

@ -68,6 +68,7 @@ pub fn expand_derive_entity_model(data: Data, attrs: Vec<Attribute>) -> syn::Res
let mut default_value = None;
let mut default_expr = None;
let mut indexed = false;
let mut ignore = false;
let mut unique = false;
let mut sql_type = None;
// search for #[sea_orm(primary_key, auto_increment = false, column_type = "String(Some(255))", default_value = "new user", default_expr = "gen_random_uuid()", nullable, indexed, unique)]
@ -120,7 +121,10 @@ pub fn expand_derive_entity_model(data: Data, attrs: Vec<Attribute>) -> syn::Res
}
Meta::Path(p) => {
if let Some(name) = p.get_ident() {
if name == "primary_key" {
if name == "ignore" {
ignore = true;
break;
} else if name == "primary_key" {
primary_keys.push(quote! { #field_name });
primary_key_types.push(field.ty.clone());
} else if name == "nullable" {
@ -138,6 +142,11 @@ pub fn expand_derive_entity_model(data: Data, attrs: Vec<Attribute>) -> syn::Res
}
}
if ignore {
columns_enum.pop();
continue;
}
let field_type = match sql_type {
Some(t) => t,
None => {

View File

@ -1,8 +1,9 @@
use crate::attributes::derive_attr;
use crate::{attributes::derive_attr, util::field_not_ignored};
use heck::CamelCase;
use proc_macro2::TokenStream;
use quote::{format_ident, quote, quote_spanned};
use std::iter::FromIterator;
use syn::Ident;
enum Error {
InputNotStruct,
@ -14,6 +15,7 @@ struct DeriveModel {
entity_ident: syn::Ident,
field_idents: Vec<syn::Ident>,
ident: syn::Ident,
ignore_attrs: Vec<bool>,
}
impl DeriveModel {
@ -48,11 +50,17 @@ impl DeriveModel {
})
.collect();
let ignore_attrs = fields
.iter()
.map(|field| !field_not_ignored(field))
.collect();
Ok(DeriveModel {
column_idents,
entity_ident,
field_idents,
ident,
ignore_attrs,
})
}
@ -70,23 +78,56 @@ impl DeriveModel {
let ident = &self.ident;
let field_idents = &self.field_idents;
let column_idents = &self.column_idents;
let field_values: Vec<TokenStream> = column_idents
.iter()
.zip(&self.ignore_attrs)
.map(|(column_ident, ignore)| {
if *ignore {
quote! {
Default::default()
}
} else {
quote! {
row.try_get(pre, sea_orm::IdenStatic::as_str(&<<Self as sea_orm::ModelTrait>::Entity as sea_orm::entity::EntityTrait>::Column::#column_ident).into())?
}
}
})
.collect();
quote!(
impl sea_orm::FromQueryResult for #ident {
fn from_query_result(row: &sea_orm::QueryResult, pre: &str) -> Result<Self, sea_orm::DbErr> {
Ok(Self {
#(#field_idents: row.try_get(pre, sea_orm::IdenStatic::as_str(&<<Self as sea_orm::ModelTrait>::Entity as sea_orm::entity::EntityTrait>::Column::#column_idents).into())?),*
#(#field_idents: #field_values),*
})
}
}
)
}
fn impl_model_trait(&self) -> TokenStream {
fn impl_model_trait<'a>(&'a self) -> TokenStream {
let ident = &self.ident;
let entity_ident = &self.entity_ident;
let field_idents = &self.field_idents;
let column_idents = &self.column_idents;
let ignore_attrs = &self.ignore_attrs;
let ignore = |(ident, ignore): (&'a Ident, &bool)| -> Option<&'a Ident> {
if *ignore {
None
} else {
Some(ident)
}
};
let field_idents: Vec<&Ident> = self
.field_idents
.iter()
.zip(ignore_attrs)
.filter_map(ignore)
.collect();
let column_idents: Vec<&Ident> = self
.column_idents
.iter()
.zip(ignore_attrs)
.filter_map(ignore)
.collect();
let missing_field_msg = format!("field does not exist on {}", ident);

View File

@ -5,6 +5,7 @@ use syn::{parse_macro_input, DeriveInput, Error};
mod attributes;
mod derives;
mod util;
#[proc_macro_derive(DeriveEntity, attributes(sea_orm))]
pub fn derive_entity(input: TokenStream) -> TokenStream {
@ -73,7 +74,7 @@ pub fn derive_model(input: TokenStream) -> TokenStream {
.into()
}
#[proc_macro_derive(DeriveActiveModel)]
#[proc_macro_derive(DeriveActiveModel, attributes(sea_orm))]
pub fn derive_active_model(input: TokenStream) -> TokenStream {
let DeriveInput { ident, data, .. } = parse_macro_input!(input);

View File

@ -0,0 +1,26 @@
use syn::{punctuated::Punctuated, token::Comma, Field, Meta};
pub(crate) fn field_not_ignored(field: &Field) -> bool {
for attr in field.attrs.iter() {
if let Some(ident) = attr.path.get_ident() {
if ident != "sea_orm" {
continue;
}
} else {
continue;
}
if let Ok(list) = attr.parse_args_with(Punctuated::<Meta, Comma>::parse_terminated) {
for meta in list.iter() {
if let Meta::Path(path) = meta {
if let Some(name) = path.get_ident() {
if name == "ignore" {
return false;
}
}
}
}
}
}
true
}

View File

@ -19,6 +19,8 @@ pub struct Model {
pub cake_id: i32,
pub filling_id: i32,
pub price: Decimal,
#[sea_orm(ignore)]
pub ignored_attr: i32,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)]

View File

@ -9,6 +9,8 @@ pub struct Entity;
pub struct Model {
pub id: i32,
pub name: String,
#[sea_orm(ignore)]
pub ignored_attr: i32,
}
// If your column names are not in snake-case, derive `DeriveCustomColumn` here.