diff --git a/sea-orm-cli/Cargo.toml b/sea-orm-cli/Cargo.toml index 07db2e4b..f24eead5 100644 --- a/sea-orm-cli/Cargo.toml +++ b/sea-orm-cli/Cargo.toml @@ -59,3 +59,4 @@ runtime-tokio-rustls = [ "sqlx/runtime-tokio-rustls", "sea-schema/runtime-tokio-rustls", ] + diff --git a/sea-orm-cli/src/cli.rs b/sea-orm-cli/src/cli.rs index 8fe9c4a4..f0d12b7b 100644 --- a/sea-orm-cli/src/cli.rs +++ b/sea-orm-cli/src/cli.rs @@ -63,6 +63,13 @@ pub fn build_cli() -> App<'static, 'static> { .help("Generate entity file of compact format") .takes_value(false) .conflicts_with("EXPANDED_FORMAT"), + ) + .arg( + Arg::with_name("WITH_SERDE") + .long("with-serde") + .help("Automatically derive serde Serialize / Deserialize traits for the entity (none, serialize, deserialize, both)") + .takes_value(true) + .default_value("none") ), ) .setting(AppSettings::SubcommandRequiredElseHelp); diff --git a/sea-orm-cli/src/main.rs b/sea-orm-cli/src/main.rs index c318a510..528ce5f5 100644 --- a/sea-orm-cli/src/main.rs +++ b/sea-orm-cli/src/main.rs @@ -1,8 +1,8 @@ use clap::ArgMatches; use dotenv::dotenv; use log::LevelFilter; -use sea_orm_codegen::{EntityTransformer, OutputFile}; -use std::{error::Error, fmt::Display, fs, io::Write, path::Path, process::Command}; +use sea_orm_codegen::{EntityTransformer, OutputFile, WithSerde}; +use std::{error::Error, fmt::Display, fs, io::Write, path::Path, process::Command, str::FromStr}; mod cli; @@ -26,13 +26,17 @@ async fn run_generate_command(matches: &ArgMatches<'_>) -> Result<(), Box>(); + let tables = args + .values_of("TABLES") + .unwrap_or_default() + .collect::>(); let expanded_format = args.is_present("EXPANDED_FORMAT"); + let with_serde = args.value_of("WITH_SERDE").unwrap(); let filter_tables = |table: &str| -> bool { if tables.len() > 0 { return tables.contains(&table); } - + true }; let filter_hidden_tables = |table: &str| -> bool { @@ -84,7 +88,8 @@ async fn run_generate_command(matches: &ArgMatches<'_>) -> Result<(), Box Result { + Ok(match s { + "none" => Self::None, + "serialize" => Self::Serialize, + "deserialize" => Self::Deserialize, + "both" => Self::Both, + v => { + return Err(crate::Error::TransformError(format!( + "Unsupported enum variant '{}'", + v + ))) + } + }) + } +} + impl EntityWriter { - pub fn generate(self, expanded_format: bool) -> WriterOutput { + pub fn generate(self, expanded_format: bool, with_serde: WithSerde) -> WriterOutput { let mut files = Vec::new(); - files.extend(self.write_entities(expanded_format)); + files.extend(self.write_entities(expanded_format, with_serde)); files.push(self.write_mod()); files.push(self.write_prelude()); WriterOutput { files } } - pub fn write_entities(&self, expanded_format: bool) -> Vec { + pub fn write_entities(&self, expanded_format: bool, with_serde: WithSerde) -> Vec { self.entities .iter() .map(|entity| { let mut lines = Vec::new(); Self::write_doc_comment(&mut lines); let code_blocks = if expanded_format { - Self::gen_expanded_code_blocks(entity) + Self::gen_expanded_code_blocks(entity, &with_serde) } else { - Self::gen_compact_code_blocks(entity) + Self::gen_compact_code_blocks(entity, &with_serde) }; Self::write(&mut lines, code_blocks); OutputFile { @@ -102,12 +131,12 @@ impl EntityWriter { lines.push("".to_owned()); } - pub fn gen_expanded_code_blocks(entity: &Entity) -> Vec { + pub fn gen_expanded_code_blocks(entity: &Entity, with_serde: &WithSerde) -> Vec { let mut code_blocks = vec![ - Self::gen_import(), + Self::gen_import(with_serde), Self::gen_entity_struct(), Self::gen_impl_entity_name(entity), - Self::gen_model_struct(entity), + Self::gen_model_struct(entity, with_serde), Self::gen_column_enum(entity), Self::gen_primary_key_enum(entity), Self::gen_impl_primary_key(entity), @@ -121,8 +150,11 @@ impl EntityWriter { code_blocks } - pub fn gen_compact_code_blocks(entity: &Entity) -> Vec { - let mut code_blocks = vec![Self::gen_import(), Self::gen_compact_model_struct(entity)]; + pub fn gen_compact_code_blocks(entity: &Entity, with_serde: &WithSerde) -> Vec { + let mut code_blocks = vec![ + Self::gen_import(with_serde), + Self::gen_compact_model_struct(entity, with_serde), + ]; let relation_defs = if entity.get_relation_ref_tables_camel_case().is_empty() { vec![ Self::gen_relation_enum(entity), @@ -138,9 +170,33 @@ impl EntityWriter { code_blocks } - pub fn gen_import() -> TokenStream { - quote! { - use sea_orm::entity::prelude::*; + pub fn gen_import(with_serde: &WithSerde) -> TokenStream { + match with_serde { + WithSerde::None => { + quote! { + use sea_orm::entity::prelude::*; + } + } + WithSerde::Serialize => { + quote! { + use sea_orm::entity::prelude::*; + use serde::Serialize; + } + } + + WithSerde::Deserialize => { + quote! { + use sea_orm::entity::prelude::*; + use serde::Deserialize; + } + } + + WithSerde::Both => { + quote! { + use sea_orm::entity::prelude::*; + use serde::{Deserialize,Serialize}; + } + } } } @@ -162,13 +218,44 @@ impl EntityWriter { } } - pub fn gen_model_struct(entity: &Entity) -> TokenStream { + pub fn gen_model_struct(entity: &Entity, with_serde: &WithSerde) -> TokenStream { let column_names_snake_case = entity.get_column_names_snake_case(); let column_rs_types = entity.get_column_rs_types(); - quote! { - #[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel)] - pub struct Model { - #(pub #column_names_snake_case: #column_rs_types,)* + + match with_serde { + WithSerde::None => { + quote! { + #[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel)] + pub struct Model { + #(pub #column_names_snake_case: #column_rs_types,)* + } + } + } + WithSerde::Serialize => { + quote! { + #[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel, Serialize)] + pub struct Model { + #(pub #column_names_snake_case: #column_rs_types,)* + } + } + } + + WithSerde::Deserialize => { + quote! { + #[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel, Deserialize)] + pub struct Model { + #(pub #column_names_snake_case: #column_rs_types,)* + } + } + } + + WithSerde::Both => { + quote! { + #[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel, Serialize, Deserialize)] + pub struct Model { + #(pub #column_names_snake_case: #column_rs_types,)* + } + } } } } @@ -320,7 +407,7 @@ impl EntityWriter { } } - pub fn gen_compact_model_struct(entity: &Entity) -> TokenStream { + pub fn gen_compact_model_struct(entity: &Entity, with_serde: &WithSerde) -> TokenStream { let table_name = entity.table_name.as_str(); let column_names_snake_case = entity.get_column_names_snake_case(); let column_rs_types = entity.get_column_rs_types(); @@ -365,14 +452,57 @@ impl EntityWriter { } }) .collect(); - quote! { - #[derive(Clone, Debug, PartialEq, DeriveEntityModel)] - #[sea_orm(table_name = #table_name)] - pub struct Model { - #( - #attrs - pub #column_names_snake_case: #column_rs_types, - )* + + match with_serde { + WithSerde::None => { + quote! { + #[derive(Clone, Debug, PartialEq, DeriveEntityModel)] + #[sea_orm(table_name = #table_name)] + pub struct Model { + #( + #attrs + pub #column_names_snake_case: #column_rs_types, + )* + } + } + } + WithSerde::Serialize => { + quote! { + #[derive(Clone, Debug, PartialEq, DeriveEntityModel, Serialize)] + #[sea_orm(table_name = #table_name)] + pub struct Model { + #( + #attrs + pub #column_names_snake_case: #column_rs_types, + )* + } + } + } + + WithSerde::Deserialize => { + quote! { + #[derive(Clone, Debug, PartialEq, DeriveEntityModel, Deserialize)] + #[sea_orm(table_name = #table_name)] + pub struct Model { + #( + #attrs + pub #column_names_snake_case: #column_rs_types, + )* + } + } + } + + WithSerde::Both => { + quote! { + #[derive(Clone, Debug, PartialEq, DeriveEntityModel, Serialize, Deserialize)] + #[sea_orm(table_name = #table_name)] + pub struct Model { + #( + #attrs + pub #column_names_snake_case: #column_rs_types, + )* + } + } } } } @@ -396,6 +526,7 @@ impl EntityWriter { mod tests { use crate::{ Column, ConjunctRelation, Entity, EntityWriter, PrimaryKey, Relation, RelationType, + WithSerde, }; use pretty_assertions::assert_eq; use proc_macro2::TokenStream; @@ -693,7 +824,7 @@ mod tests { } let content = lines.join(""); let expected: TokenStream = content.parse().unwrap(); - let generated = EntityWriter::gen_expanded_code_blocks(entity) + let generated = EntityWriter::gen_expanded_code_blocks(entity, &crate::WithSerde::None) .into_iter() .skip(1) .fold(TokenStream::new(), |mut acc, tok| { @@ -733,7 +864,7 @@ mod tests { } let content = lines.join(""); let expected: TokenStream = content.parse().unwrap(); - let generated = EntityWriter::gen_compact_code_blocks(entity) + let generated = EntityWriter::gen_compact_code_blocks(entity, &crate::WithSerde::None) .into_iter() .skip(1) .fold(TokenStream::new(), |mut acc, tok| { @@ -745,4 +876,109 @@ mod tests { Ok(()) } + + #[test] + fn test_gen_with_serde() -> io::Result<()> { + let cake_entity = setup().get(0).unwrap().clone(); + + assert_eq!(cake_entity.get_table_name_snake_case(), "cake"); + + // Compact code blocks + assert_serde_variant_results( + &cake_entity, + &( + include_str!("../../tests/compact_with_serde/cake_none.rs").into(), + WithSerde::None, + ), + Box::new(EntityWriter::gen_compact_code_blocks), + )?; + assert_serde_variant_results( + &cake_entity, + &( + include_str!("../../tests/compact_with_serde/cake_serialize.rs").into(), + WithSerde::Serialize, + ), + Box::new(EntityWriter::gen_compact_code_blocks), + )?; + assert_serde_variant_results( + &cake_entity, + &( + include_str!("../../tests/compact_with_serde/cake_deserialize.rs").into(), + WithSerde::Deserialize, + ), + Box::new(EntityWriter::gen_compact_code_blocks), + )?; + assert_serde_variant_results( + &cake_entity, + &( + include_str!("../../tests/compact_with_serde/cake_both.rs").into(), + WithSerde::Both, + ), + Box::new(EntityWriter::gen_compact_code_blocks), + )?; + + // Expanded code blocks + assert_serde_variant_results( + &cake_entity, + &( + include_str!("../../tests/expanded_with_serde/cake_none.rs").into(), + WithSerde::None, + ), + Box::new(EntityWriter::gen_expanded_code_blocks), + )?; + assert_serde_variant_results( + &cake_entity, + &( + include_str!("../../tests/expanded_with_serde/cake_serialize.rs").into(), + WithSerde::Serialize, + ), + Box::new(EntityWriter::gen_expanded_code_blocks), + )?; + assert_serde_variant_results( + &cake_entity, + &( + include_str!("../../tests/expanded_with_serde/cake_deserialize.rs").into(), + WithSerde::Deserialize, + ), + Box::new(EntityWriter::gen_expanded_code_blocks), + )?; + assert_serde_variant_results( + &cake_entity, + &( + include_str!("../../tests/expanded_with_serde/cake_both.rs").into(), + WithSerde::Both, + ), + Box::new(EntityWriter::gen_expanded_code_blocks), + )?; + + Ok(()) + } + + fn assert_serde_variant_results( + cake_entity: &Entity, + entity_serde_variant: &(String, WithSerde), + generator: Box Vec>, + ) -> io::Result<()> { + let mut reader = BufReader::new(entity_serde_variant.0.as_bytes()); + let mut lines: Vec = Vec::new(); + + reader.read_until(b'\n', &mut Vec::new())?; + + let mut line = String::new(); + while reader.read_line(&mut line)? > 0 { + lines.push(line.to_owned()); + line.clear(); + } + let content = lines.join(""); + let expected: TokenStream = content.parse().unwrap(); + let generated = generator(&cake_entity, &entity_serde_variant.1) + .into_iter() + .fold(TokenStream::new(), |mut acc, tok| { + acc.extend(tok); + acc + }); + + assert_eq!(expected.to_string(), generated.to_string()); + Ok(()) + } } diff --git a/sea-orm-codegen/tests/compact_with_serde/cake_both.rs b/sea-orm-codegen/tests/compact_with_serde/cake_both.rs new file mode 100644 index 00000000..3a1bea9a --- /dev/null +++ b/sea-orm-codegen/tests/compact_with_serde/cake_both.rs @@ -0,0 +1,36 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.1.0 + +use sea_orm::entity::prelude:: * ; +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Serialize, Deserialize)] +#[sea_orm(table_name = "cake")] +pub struct Model { + #[sea_orm(primary_key)] + pub id: i32, + #[sea_orm(column_type = "Text", nullable)] + pub name: Option , +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm(has_many = "super::fruit::Entity")] + Fruit, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Fruit.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + super::cake_filling::Relation::Filling.def() + } + fn via() -> Option { + Some(super::cake_filling::Relation::Cake.def().rev()) + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/sea-orm-codegen/tests/compact_with_serde/cake_deserialize.rs b/sea-orm-codegen/tests/compact_with_serde/cake_deserialize.rs new file mode 100644 index 00000000..b36718f9 --- /dev/null +++ b/sea-orm-codegen/tests/compact_with_serde/cake_deserialize.rs @@ -0,0 +1,36 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.1.0 + +use sea_orm::entity::prelude:: * ; +use serde::Deserialize; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Deserialize)] +#[sea_orm(table_name = "cake")] +pub struct Model { + #[sea_orm(primary_key)] + pub id: i32, + #[sea_orm(column_type = "Text", nullable)] + pub name: Option , +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm(has_many = "super::fruit::Entity")] + Fruit, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Fruit.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + super::cake_filling::Relation::Filling.def() + } + fn via() -> Option { + Some(super::cake_filling::Relation::Cake.def().rev()) + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/sea-orm-codegen/tests/compact_with_serde/cake_none.rs b/sea-orm-codegen/tests/compact_with_serde/cake_none.rs new file mode 100644 index 00000000..809b9051 --- /dev/null +++ b/sea-orm-codegen/tests/compact_with_serde/cake_none.rs @@ -0,0 +1,35 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.1.0 + +use sea_orm::entity::prelude:: * ; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel)] +#[sea_orm(table_name = "cake")] +pub struct Model { + #[sea_orm(primary_key)] + pub id: i32, + #[sea_orm(column_type = "Text", nullable)] + pub name: Option , +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm(has_many = "super::fruit::Entity")] + Fruit, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Fruit.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + super::cake_filling::Relation::Filling.def() + } + fn via() -> Option { + Some(super::cake_filling::Relation::Cake.def().rev()) + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/sea-orm-codegen/tests/compact_with_serde/cake_serialize.rs b/sea-orm-codegen/tests/compact_with_serde/cake_serialize.rs new file mode 100644 index 00000000..81cc3907 --- /dev/null +++ b/sea-orm-codegen/tests/compact_with_serde/cake_serialize.rs @@ -0,0 +1,36 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.1.0 + +use sea_orm::entity::prelude:: * ; +use serde::Serialize; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Serialize)] +#[sea_orm(table_name = "cake")] +pub struct Model { + #[sea_orm(primary_key)] + pub id: i32, + #[sea_orm(column_type = "Text", nullable)] + pub name: Option , +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm(has_many = "super::fruit::Entity")] + Fruit, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Fruit.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + super::cake_filling::Relation::Filling.def() + } + fn via() -> Option { + Some(super::cake_filling::Relation::Cake.def().rev()) + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/sea-orm-codegen/tests/expanded_with_serde/cake_both.rs b/sea-orm-codegen/tests/expanded_with_serde/cake_both.rs new file mode 100644 index 00000000..88821135 --- /dev/null +++ b/sea-orm-codegen/tests/expanded_with_serde/cake_both.rs @@ -0,0 +1,78 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.1.0 + +use sea_orm::entity::prelude:: * ; +use serde::{Deserialize,Serialize}; + +#[derive(Copy, Clone, Default, Debug, DeriveEntity)] +pub struct Entity; + +impl EntityName for Entity { + fn table_name(&self) -> &str { + "cake" + } +} + +#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel, Serialize, Deserialize)] +pub struct Model { + pub id: i32, + pub name: Option , +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)] +pub enum Column { + Id, + Name, +} + +#[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)] +pub enum PrimaryKey { + Id, +} + +impl PrimaryKeyTrait for PrimaryKey { + type ValueType = i32; + + fn auto_increment() -> bool { + true + } +} + +#[derive(Copy, Clone, Debug, EnumIter)] +pub enum Relation { + Fruit, +} + +impl ColumnTrait for Column { + type EntityName = Entity; + fn def(&self) -> ColumnDef { + match self { + Self::Id => ColumnType::Integer.def(), + Self::Name => ColumnType::Text.def().null(), + } + } +} + +impl RelationTrait for Relation { + fn def(&self) -> RelationDef { + match self { + Self::Fruit => Entity::has_many(super::fruit::Entity).into(), + } + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Fruit.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + super::cake_filling::Relation::Filling.def() + } + fn via() -> Option { + Some(super::cake_filling::Relation::Cake.def().rev()) + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/sea-orm-codegen/tests/expanded_with_serde/cake_deserialize.rs b/sea-orm-codegen/tests/expanded_with_serde/cake_deserialize.rs new file mode 100644 index 00000000..068f17da --- /dev/null +++ b/sea-orm-codegen/tests/expanded_with_serde/cake_deserialize.rs @@ -0,0 +1,78 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.1.0 + +use sea_orm::entity::prelude:: * ; +use serde::Deserialize; + +#[derive(Copy, Clone, Default, Debug, DeriveEntity)] +pub struct Entity; + +impl EntityName for Entity { + fn table_name(&self) -> &str { + "cake" + } +} + +#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel, Deserialize)] +pub struct Model { + pub id: i32, + pub name: Option , +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)] +pub enum Column { + Id, + Name, +} + +#[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)] +pub enum PrimaryKey { + Id, +} + +impl PrimaryKeyTrait for PrimaryKey { + type ValueType = i32; + + fn auto_increment() -> bool { + true + } +} + +#[derive(Copy, Clone, Debug, EnumIter)] +pub enum Relation { + Fruit, +} + +impl ColumnTrait for Column { + type EntityName = Entity; + fn def(&self) -> ColumnDef { + match self { + Self::Id => ColumnType::Integer.def(), + Self::Name => ColumnType::Text.def().null(), + } + } +} + +impl RelationTrait for Relation { + fn def(&self) -> RelationDef { + match self { + Self::Fruit => Entity::has_many(super::fruit::Entity).into(), + } + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Fruit.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + super::cake_filling::Relation::Filling.def() + } + fn via() -> Option { + Some(super::cake_filling::Relation::Cake.def().rev()) + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/sea-orm-codegen/tests/expanded_with_serde/cake_none.rs b/sea-orm-codegen/tests/expanded_with_serde/cake_none.rs new file mode 100644 index 00000000..d0a1299a --- /dev/null +++ b/sea-orm-codegen/tests/expanded_with_serde/cake_none.rs @@ -0,0 +1,77 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.1.0 + +use sea_orm::entity::prelude:: * ; + +#[derive(Copy, Clone, Default, Debug, DeriveEntity)] +pub struct Entity; + +impl EntityName for Entity { + fn table_name(&self) -> &str { + "cake" + } +} + +#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel)] +pub struct Model { + pub id: i32, + pub name: Option , +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)] +pub enum Column { + Id, + Name, +} + +#[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)] +pub enum PrimaryKey { + Id, +} + +impl PrimaryKeyTrait for PrimaryKey { + type ValueType = i32; + + fn auto_increment() -> bool { + true + } +} + +#[derive(Copy, Clone, Debug, EnumIter)] +pub enum Relation { + Fruit, +} + +impl ColumnTrait for Column { + type EntityName = Entity; + fn def(&self) -> ColumnDef { + match self { + Self::Id => ColumnType::Integer.def(), + Self::Name => ColumnType::Text.def().null(), + } + } +} + +impl RelationTrait for Relation { + fn def(&self) -> RelationDef { + match self { + Self::Fruit => Entity::has_many(super::fruit::Entity).into(), + } + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Fruit.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + super::cake_filling::Relation::Filling.def() + } + fn via() -> Option { + Some(super::cake_filling::Relation::Cake.def().rev()) + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/sea-orm-codegen/tests/expanded_with_serde/cake_serialize.rs b/sea-orm-codegen/tests/expanded_with_serde/cake_serialize.rs new file mode 100644 index 00000000..30313fa1 --- /dev/null +++ b/sea-orm-codegen/tests/expanded_with_serde/cake_serialize.rs @@ -0,0 +1,78 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.1.0 + +use sea_orm::entity::prelude:: * ; +use serde::Serialize; + +#[derive(Copy, Clone, Default, Debug, DeriveEntity)] +pub struct Entity; + +impl EntityName for Entity { + fn table_name(&self) -> &str { + "cake" + } +} + +#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel, Serialize)] +pub struct Model { + pub id: i32, + pub name: Option , +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)] +pub enum Column { + Id, + Name, +} + +#[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)] +pub enum PrimaryKey { + Id, +} + +impl PrimaryKeyTrait for PrimaryKey { + type ValueType = i32; + + fn auto_increment() -> bool { + true + } +} + +#[derive(Copy, Clone, Debug, EnumIter)] +pub enum Relation { + Fruit, +} + +impl ColumnTrait for Column { + type EntityName = Entity; + fn def(&self) -> ColumnDef { + match self { + Self::Id => ColumnType::Integer.def(), + Self::Name => ColumnType::Text.def().null(), + } + } +} + +impl RelationTrait for Relation { + fn def(&self) -> RelationDef { + match self { + Self::Fruit => Entity::has_many(super::fruit::Entity).into(), + } + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Fruit.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + super::cake_filling::Relation::Filling.def() + } + fn via() -> Option { + Some(super::cake_filling::Relation::Cake.def().rev()) + } +} + +impl ActiveModelBehavior for ActiveModel {}