Try DeriveRelation

This commit is contained in:
Chris Tsang 2021-09-07 22:43:16 +08:00
parent 0f0d5b52b4
commit a186338ff5
8 changed files with 89 additions and 60 deletions

View File

@ -19,6 +19,8 @@ pub mod field_attr {
#[derive(Default, FromAttributes)] #[derive(Default, FromAttributes)]
pub struct SeaOrm { pub struct SeaOrm {
pub belongs_to: Option<syn::Lit>, pub belongs_to: Option<syn::Lit>,
pub has_one: Option<syn::Lit>,
pub has_many: Option<syn::Lit>,
pub from: Option<syn::Lit>, pub from: Option<syn::Lit>,
pub to: Option<syn::Lit>, pub to: Option<syn::Lit>,
} }

View File

@ -101,18 +101,19 @@ pub fn expand_derive_entity_model(data: Data, attrs: Vec<Attribute>) -> syn::Res
} }
} else if name == "auto_increment" { } else if name == "auto_increment" {
if let Lit::Str(litstr) = &nv.lit { if let Lit::Str(litstr) = &nv.lit {
auto_increment = auto_increment = match litstr.value().as_str() {
match litstr.value().as_str() { "true" => true,
"true" => true, "false" => false,
"false" => false, _ => {
_ => return Err(Error::new( return Err(Error::new(
field.span(), field.span(),
format!( format!(
"Invalid auto_increment = {}", "Invalid auto_increment = {}",
litstr.value() litstr.value()
), ),
)), ))
}; }
};
} else { } else {
return Err(Error::new( return Err(Error::new(
field.span(), field.span(),

View File

@ -1,8 +1,8 @@
use std::iter::FromIterator; use crate::attributes::derive_attr;
use heck::CamelCase; use heck::CamelCase;
use proc_macro2::TokenStream; use proc_macro2::TokenStream;
use quote::{format_ident, quote, quote_spanned}; use quote::{format_ident, quote, quote_spanned};
use crate::attributes::derive_attr; use std::iter::FromIterator;
enum Error { enum Error {
InputNotStruct, InputNotStruct,

View File

@ -52,32 +52,71 @@ impl DeriveRelation {
.map(|variant| { .map(|variant| {
let variant_ident = &variant.ident; let variant_ident = &variant.ident;
let attr = field_attr::SeaOrm::from_attributes(&variant.attrs)?; let attr = field_attr::SeaOrm::from_attributes(&variant.attrs)?;
let belongs_to = attr let mut relation_type = quote! { error };
.belongs_to let related_to = if attr.belongs_to.is_some() {
.as_ref() relation_type = quote! { belongs_to };
.map(Self::parse_lit_string) attr.belongs_to
.ok_or_else(|| { .as_ref()
syn::Error::new_spanned(variant, "Missing attribute 'belongs_to'") .map(Self::parse_lit_string)
})??; .ok_or_else(|| {
let from = attr syn::Error::new_spanned(variant, "Missing value for 'belongs_to'")
.from })
.as_ref() } else if attr.has_one.is_some() {
.map(Self::parse_lit_string) relation_type = quote! { has_one };
.ok_or_else(|| { attr.has_one
syn::Error::new_spanned(variant, "Missing attribute 'from'") .as_ref()
})??; .map(Self::parse_lit_string)
let to = attr .ok_or_else(|| {
.to syn::Error::new_spanned(variant, "Missing value for 'has_one'")
.as_ref() })
.map(Self::parse_lit_string) } else if attr.has_many.is_some() {
.ok_or_else(|| syn::Error::new_spanned(variant, "Missing attribute 'to'"))??; relation_type = quote! { has_many };
attr.has_many
.as_ref()
.map(Self::parse_lit_string)
.ok_or_else(|| {
syn::Error::new_spanned(variant, "Missing value for 'has_many'")
})
} else {
Err(syn::Error::new_spanned(
variant,
"Missing one of 'has_one', 'has_many' or 'belongs_to'",
))
}??;
Result::<_, syn::Error>::Ok(quote!( let mut result = quote!(
Self::#variant_ident => #entity_ident::belongs_to(#belongs_to) Self::#variant_ident => #entity_ident::#relation_type(#related_to)
.from(#from) );
.to(#to)
.into() if attr.from.is_some() {
)) let from =
attr.from
.as_ref()
.map(Self::parse_lit_string)
.ok_or_else(|| {
syn::Error::new_spanned(variant, "Missing value for 'from'")
})??;
result = quote! { #result.from(#from) };
} else if attr.belongs_to.is_some() {
return Err(syn::Error::new_spanned(variant, "Missing attribute 'from'"));
}
if attr.to.is_some() {
let to = attr
.to
.as_ref()
.map(Self::parse_lit_string)
.ok_or_else(|| {
syn::Error::new_spanned(variant, "Missing value for 'to'")
})??;
result = quote! { #result.to(#to) };
} else if attr.belongs_to.is_some() {
return Err(syn::Error::new_spanned(variant, "Missing attribute 'to'"));
}
result = quote! { #result.into() };
Result::<_, syn::Error>::Ok(result)
}) })
.collect::<Result<Vec<_>, _>>()?; .collect::<Result<Vec<_>, _>>()?;

View File

@ -1,9 +1,9 @@
pub use crate::{ pub use crate::{
error::*, ActiveModelBehavior, ActiveModelTrait, ColumnDef, ColumnTrait, ColumnType, error::*, ActiveModelBehavior, ActiveModelTrait, ColumnDef, ColumnTrait, ColumnType,
DeriveActiveModel, DeriveActiveModelBehavior, DeriveColumn, DeriveCustomColumn, DeriveEntity, DeriveActiveModel, DeriveActiveModelBehavior, DeriveColumn, DeriveCustomColumn, DeriveEntity,
DeriveEntityModel, DeriveModel, DerivePrimaryKey, EntityName, EntityTrait, EnumIter, DeriveEntityModel, DeriveModel, DerivePrimaryKey, DeriveRelation, EntityName, EntityTrait,
ForeignKeyAction, Iden, IdenStatic, Linked, ModelTrait, PrimaryKeyToColumn, PrimaryKeyTrait, EnumIter, ForeignKeyAction, Iden, IdenStatic, Linked, ModelTrait, PrimaryKeyToColumn,
QueryFilter, QueryResult, Related, RelationDef, RelationTrait, Select, Value, PrimaryKeyTrait, QueryFilter, QueryResult, Related, RelationDef, RelationTrait, Select, Value,
}; };
#[cfg(feature = "with-json")] #[cfg(feature = "with-json")]

View File

@ -227,7 +227,7 @@ pub use query::*;
pub use sea_orm_macros::{ pub use sea_orm_macros::{
DeriveActiveModel, DeriveActiveModelBehavior, DeriveColumn, DeriveCustomColumn, DeriveEntity, DeriveActiveModel, DeriveActiveModelBehavior, DeriveColumn, DeriveCustomColumn, DeriveEntity,
DeriveEntityModel, DeriveModel, DerivePrimaryKey, FromQueryResult, DeriveEntityModel, DeriveModel, DerivePrimaryKey, DeriveRelation, FromQueryResult,
}; };
pub use sea_query; pub use sea_query;

View File

@ -1,5 +1,5 @@
use crate as sea_orm; use crate as sea_orm;
use sea_orm::entity::prelude::*; use crate::entity::prelude::*;
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, DeriveModel, DeriveActiveModel)] #[derive(Clone, Debug, PartialEq, DeriveEntityModel, DeriveModel, DeriveActiveModel)]
#[sea_orm(table_name = "cake")] #[sea_orm(table_name = "cake")]
@ -9,19 +9,12 @@ pub struct Model {
pub name: String, pub name: String,
} }
#[derive(Copy, Clone, Debug, EnumIter)] #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation { pub enum Relation {
#[sea_orm(has_many = "super::fruit::Entity")]
Fruit, Fruit,
} }
impl RelationTrait for Relation {
fn def(&self) -> RelationDef {
match self {
Self::Fruit => Entity::has_many(super::fruit::Entity).into(),
}
}
}
impl Related<super::fruit::Entity> for Entity { impl Related<super::fruit::Entity> for Entity {
fn to() -> RelationDef { fn to() -> RelationDef {
Relation::Fruit.def() Relation::Fruit.def()

View File

@ -32,8 +32,13 @@ impl PrimaryKeyTrait for PrimaryKey {
} }
} }
#[derive(Copy, Clone, Debug, EnumIter)] #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation { pub enum Relation {
#[sea_orm(
belongs_to = "super::cake::Entity",
from = "Column::CakeId",
to = "super::cake::Column::Id"
)]
Cake, Cake,
} }
@ -49,17 +54,6 @@ impl ColumnTrait for Column {
} }
} }
impl RelationTrait for Relation {
fn def(&self) -> RelationDef {
match self {
Self::Cake => Entity::belongs_to(super::cake::Entity)
.from(Column::CakeId)
.to(super::cake::Column::Id)
.into(),
}
}
}
impl Related<super::cake::Entity> for Entity { impl Related<super::cake::Entity> for Entity {
fn to() -> RelationDef { fn to() -> RelationDef {
Relation::Cake.def() Relation::Cake.def()