From b62243d00fd8c1dfc310d28ea01cc8a96ccd5f94 Mon Sep 17 00:00:00 2001 From: Isaiah Gamble <77396670+tsar-boomba@users.noreply.github.com> Date: Mon, 19 Dec 2022 22:35:10 -0500 Subject: [PATCH] sea-orm-cli Implement derives & attributes parameters for entity generation (#1124) * implement derives & attributes for cli * fmt and clippy fix * use comma delimiter for attributes arg * Update help message use `'` instead of `"` to quote * Refactoring * remove unnecessary cloning Co-authored-by: Billy Chan --- sea-orm-cli/src/cli.rs | 18 + sea-orm-cli/src/commands/generate.rs | 4 + sea-orm-codegen/src/entity/writer.rs | 461 ++++++++++++++---- .../compact_with_attributes/cake_multiple.rs | 37 ++ .../compact_with_attributes/cake_none.rs | 35 ++ .../tests/compact_with_attributes/cake_one.rs | 36 ++ .../compact_with_derives/cake_multiple.rs | 35 ++ .../tests/compact_with_derives/cake_none.rs | 35 ++ .../tests/compact_with_derives/cake_one.rs | 35 ++ .../expanded_with_attributes/cake_multiple.rs | 79 +++ .../expanded_with_attributes/cake_none.rs | 77 +++ .../expanded_with_attributes/cake_one.rs | 78 +++ .../expanded_with_derives/cake_multiple.rs | 77 +++ .../tests/expanded_with_derives/cake_none.rs | 77 +++ .../tests/expanded_with_derives/cake_one.rs | 77 +++ 15 files changed, 1063 insertions(+), 98 deletions(-) create mode 100644 sea-orm-codegen/tests/compact_with_attributes/cake_multiple.rs create mode 100644 sea-orm-codegen/tests/compact_with_attributes/cake_none.rs create mode 100644 sea-orm-codegen/tests/compact_with_attributes/cake_one.rs create mode 100644 sea-orm-codegen/tests/compact_with_derives/cake_multiple.rs create mode 100644 sea-orm-codegen/tests/compact_with_derives/cake_none.rs create mode 100644 sea-orm-codegen/tests/compact_with_derives/cake_one.rs create mode 100644 sea-orm-codegen/tests/expanded_with_attributes/cake_multiple.rs create mode 100644 sea-orm-codegen/tests/expanded_with_attributes/cake_none.rs create mode 100644 sea-orm-codegen/tests/expanded_with_attributes/cake_one.rs create mode 100644 sea-orm-codegen/tests/expanded_with_derives/cake_multiple.rs create mode 100644 sea-orm-codegen/tests/expanded_with_derives/cake_none.rs create mode 100644 sea-orm-codegen/tests/expanded_with_derives/cake_one.rs diff --git a/sea-orm-cli/src/cli.rs b/sea-orm-cli/src/cli.rs index 1d797aa03..57270a180 100644 --- a/sea-orm-cli/src/cli.rs +++ b/sea-orm-cli/src/cli.rs @@ -228,6 +228,24 @@ pub enum GenerateSubcommands { help = "Generate index file as `lib.rs` instead of `mod.rs`." )] lib: bool, + + #[clap( + value_parser, + long, + use_value_delimiter = true, + takes_value = true, + help = "Add extra derive macros to generated model structs (comma separated), ex. `--derives 'ts_rs::Ts'`" + )] + derives: Vec, + + #[clap( + value_parser, + long, + use_value_delimiter = true, + takes_value = true, + help = r#"Add extra attributes to generated model struct, no need for `#[]` (comma separated), ex. `--attributes 'serde(rename_all = "camelCase")','ts(export)'`"# + )] + attributes: Vec, }, } diff --git a/sea-orm-cli/src/commands/generate.rs b/sea-orm-cli/src/commands/generate.rs index 8117c852d..5a8672fd2 100644 --- a/sea-orm-cli/src/commands/generate.rs +++ b/sea-orm-cli/src/commands/generate.rs @@ -27,6 +27,8 @@ pub async fn run_generate_command( with_copy_enums, date_time_crate, lib, + derives, + attributes, } => { if verbose { let _ = tracing_subscriber::fmt() @@ -160,6 +162,8 @@ pub async fn run_generate_command( let writer_context = EntityWriterContext::new( expanded_format, WithSerde::from_str(&with_serde).unwrap(), + derives, + attributes, with_copy_enums, date_time_crate.into(), schema_name, diff --git a/sea-orm-codegen/src/entity/writer.rs b/sea-orm-codegen/src/entity/writer.rs index 6f293fc7d..91981c0a4 100644 --- a/sea-orm-codegen/src/entity/writer.rs +++ b/sea-orm-codegen/src/entity/writer.rs @@ -39,6 +39,8 @@ pub enum DateTimeCrate { pub struct EntityWriterContext { pub(crate) expanded_format: bool, pub(crate) with_serde: WithSerde, + pub(crate) derives: TokenStream, + pub(crate) attributes: TokenStream, pub(crate) with_copy_enums: bool, pub(crate) date_time_crate: DateTimeCrate, pub(crate) schema_name: Option, @@ -76,6 +78,29 @@ impl WithSerde { } } +/// Converts derives argument to token stream +fn bonus_derive(derives: Vec) -> TokenStream { + derives + .into_iter() + .fold(TokenStream::default(), |derives, derive| { + let tokens: TokenStream = derive.parse().unwrap(); + quote! { #derives, #tokens } + }) +} + +/// convert attributes argument to token stream +fn bonus_attributes(attributes: Vec) -> TokenStream { + attributes + .into_iter() + .fold(TokenStream::default(), |attributes, attribute| { + let tokens: TokenStream = attribute.parse().unwrap(); + quote! { + #attributes + #[#tokens] + } + }) +} + impl FromStr for WithSerde { type Err = crate::Error; @@ -96,9 +121,12 @@ impl FromStr for WithSerde { } impl EntityWriterContext { + #[allow(clippy::too_many_arguments)] pub fn new( expanded_format: bool, with_serde: WithSerde, + derives: Vec, + attributes: Vec, with_copy_enums: bool, date_time_crate: DateTimeCrate, schema_name: Option, @@ -107,6 +135,8 @@ impl EntityWriterContext { Self { expanded_format, with_serde, + derives: bonus_derive(derives), + attributes: bonus_attributes(attributes), with_copy_enums, date_time_crate, schema_name, @@ -151,6 +181,8 @@ impl EntityWriter { Self::gen_expanded_code_blocks( entity, &context.with_serde, + &context.derives, + &context.attributes, &context.date_time_crate, &context.schema_name, ) @@ -158,6 +190,8 @@ impl EntityWriter { Self::gen_compact_code_blocks( entity, &context.with_serde, + &context.derives, + &context.attributes, &context.date_time_crate, &context.schema_name, ) @@ -257,6 +291,8 @@ impl EntityWriter { pub fn gen_expanded_code_blocks( entity: &Entity, with_serde: &WithSerde, + derives: &TokenStream, + attributes: &TokenStream, date_time_crate: &DateTimeCrate, schema_name: &Option, ) -> Vec { @@ -266,7 +302,7 @@ impl EntityWriter { imports, Self::gen_entity_struct(), Self::gen_impl_entity_name(entity, schema_name), - Self::gen_model_struct(entity, with_serde, date_time_crate), + Self::gen_model_struct(entity, with_serde, derives, attributes, date_time_crate), Self::gen_column_enum(entity), Self::gen_primary_key_enum(entity), Self::gen_impl_primary_key(entity, date_time_crate), @@ -283,6 +319,8 @@ impl EntityWriter { pub fn gen_compact_code_blocks( entity: &Entity, with_serde: &WithSerde, + derives: &TokenStream, + attributes: &TokenStream, date_time_crate: &DateTimeCrate, schema_name: &Option, ) -> Vec { @@ -290,7 +328,14 @@ impl EntityWriter { imports.extend(Self::gen_import_active_enum(entity)); let mut code_blocks = vec![ imports, - Self::gen_compact_model_struct(entity, with_serde, date_time_crate, schema_name), + Self::gen_compact_model_struct( + entity, + with_serde, + derives, + attributes, + date_time_crate, + schema_name, + ), Self::gen_compact_relation_enum(entity), ]; code_blocks.extend(Self::gen_impl_related(entity)); @@ -377,6 +422,8 @@ impl EntityWriter { pub fn gen_model_struct( entity: &Entity, with_serde: &WithSerde, + derives: &TokenStream, + attributes: &TokenStream, date_time_crate: &DateTimeCrate, ) -> TokenStream { let column_names_snake_case = entity.get_column_names_snake_case(); @@ -385,7 +432,8 @@ impl EntityWriter { let extra_derive = with_serde.extra_derive(); quote! { - #[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel #if_eq_needed #extra_derive)] + #[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel #if_eq_needed #extra_derive #derives)] + #attributes pub struct Model { #(pub #column_names_snake_case: #column_rs_types,)* } @@ -564,6 +612,8 @@ impl EntityWriter { pub fn gen_compact_model_struct( entity: &Entity, with_serde: &WithSerde, + derives: &TokenStream, + attributes: &TokenStream, date_time_crate: &DateTimeCrate, schema_name: &Option, ) -> TokenStream { @@ -625,11 +675,12 @@ impl EntityWriter { let extra_derive = with_serde.extra_derive(); quote! { - #[derive(Clone, Debug, PartialEq, DeriveEntityModel #if_eq_needed #extra_derive)] + #[derive(Clone, Debug, PartialEq, DeriveEntityModel #if_eq_needed #extra_derive #derives)] #[sea_orm( #schema_name table_name = #table_name )] + #attributes pub struct Model { #( #attrs @@ -670,6 +721,7 @@ impl EntityWriter { #[cfg(test)] mod tests { use crate::{ + entity::writer::{bonus_attributes, bonus_derive}, Column, ConjunctRelation, DateTimeCrate, Entity, EntityWriter, PrimaryKey, Relation, RelationType, WithSerde, }; @@ -1259,6 +1311,8 @@ mod tests { EntityWriter::gen_expanded_code_blocks( entity, &crate::WithSerde::None, + &bonus_derive(vec![]), + &bonus_attributes(vec![]), &crate::DateTimeCrate::Chrono, &None ) @@ -1275,6 +1329,8 @@ mod tests { EntityWriter::gen_expanded_code_blocks( entity, &crate::WithSerde::None, + &bonus_derive(vec![]), + &bonus_attributes(vec![]), &crate::DateTimeCrate::Chrono, &Some("public".to_owned()) ) @@ -1291,6 +1347,8 @@ mod tests { EntityWriter::gen_expanded_code_blocks( entity, &crate::WithSerde::None, + &bonus_derive(vec![]), + &bonus_attributes(vec![]), &crate::DateTimeCrate::Chrono, &Some("schema_name".to_owned()) ) @@ -1343,6 +1401,8 @@ mod tests { EntityWriter::gen_compact_code_blocks( entity, &crate::WithSerde::None, + &bonus_derive(vec![]), + &bonus_attributes(vec![]), &crate::DateTimeCrate::Chrono, &None ) @@ -1359,6 +1419,8 @@ mod tests { EntityWriter::gen_compact_code_blocks( entity, &crate::WithSerde::None, + &bonus_derive(vec![]), + &bonus_attributes(vec![]), &crate::DateTimeCrate::Chrono, &Some("public".to_owned()) ) @@ -1375,6 +1437,8 @@ mod tests { EntityWriter::gen_compact_code_blocks( entity, &crate::WithSerde::None, + &bonus_derive(vec![]), + &bonus_attributes(vec![]), &crate::DateTimeCrate::Chrono, &Some("schema_name".to_owned()) ) @@ -1398,93 +1462,306 @@ mod tests { 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, - 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, - None, - ), - 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, - None, - ), - 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, - None, - ), - Box::new(EntityWriter::gen_compact_code_blocks), - )?; + assert_eq!( + comparable_file_string(include_str!("../../tests/compact_with_serde/cake_none.rs"))?, + generated_to_string(EntityWriter::gen_compact_code_blocks( + &cake_entity, + &WithSerde::None, + &TokenStream::new(), + &TokenStream::new(), + &DateTimeCrate::Chrono, + &None + )) + ); + assert_eq!( + comparable_file_string(include_str!( + "../../tests/compact_with_serde/cake_serialize.rs" + ))?, + generated_to_string(EntityWriter::gen_compact_code_blocks( + &cake_entity, + &WithSerde::Serialize, + &TokenStream::new(), + &TokenStream::new(), + &DateTimeCrate::Chrono, + &None + )) + ); + assert_eq!( + comparable_file_string(include_str!( + "../../tests/compact_with_serde/cake_deserialize.rs" + ))?, + generated_to_string(EntityWriter::gen_compact_code_blocks( + &cake_entity, + &WithSerde::Deserialize, + &TokenStream::new(), + &TokenStream::new(), + &DateTimeCrate::Chrono, + &None + )) + ); + assert_eq!( + comparable_file_string(include_str!("../../tests/compact_with_serde/cake_both.rs"))?, + generated_to_string(EntityWriter::gen_compact_code_blocks( + &cake_entity, + &WithSerde::Both, + &TokenStream::new(), + &TokenStream::new(), + &DateTimeCrate::Chrono, + &None + )) + ); // Expanded code blocks - assert_serde_variant_results( - &cake_entity, - &( - include_str!("../../tests/expanded_with_serde/cake_none.rs").into(), - WithSerde::None, - 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, - None, - ), - 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, - None, - ), - 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, - None, - ), - Box::new(EntityWriter::gen_expanded_code_blocks), - )?; + assert_eq!( + comparable_file_string(include_str!("../../tests/expanded_with_serde/cake_none.rs"))?, + generated_to_string(EntityWriter::gen_expanded_code_blocks( + &cake_entity, + &WithSerde::None, + &TokenStream::new(), + &TokenStream::new(), + &DateTimeCrate::Chrono, + &None + )) + ); + assert_eq!( + comparable_file_string(include_str!( + "../../tests/expanded_with_serde/cake_serialize.rs" + ))?, + generated_to_string(EntityWriter::gen_expanded_code_blocks( + &cake_entity, + &WithSerde::Serialize, + &TokenStream::new(), + &TokenStream::new(), + &DateTimeCrate::Chrono, + &None + )) + ); + assert_eq!( + comparable_file_string(include_str!( + "../../tests/expanded_with_serde/cake_deserialize.rs" + ))?, + generated_to_string(EntityWriter::gen_expanded_code_blocks( + &cake_entity, + &WithSerde::Deserialize, + &TokenStream::new(), + &TokenStream::new(), + &DateTimeCrate::Chrono, + &None + )) + ); + assert_eq!( + comparable_file_string(include_str!("../../tests/expanded_with_serde/cake_both.rs"))?, + generated_to_string(EntityWriter::gen_expanded_code_blocks( + &cake_entity, + &WithSerde::Both, + &TokenStream::new(), + &TokenStream::new(), + &DateTimeCrate::Chrono, + &None + )) + ); + + Ok(()) + } + + #[test] + fn test_gen_with_derives() -> io::Result<()> { + let cake_entity = setup().get(0).unwrap().clone(); + + assert_eq!(cake_entity.get_table_name_snake_case(), "cake"); + + // Compact code blocks + assert_eq!( + comparable_file_string(include_str!( + "../../tests/compact_with_derives/cake_none.rs" + ))?, + generated_to_string(EntityWriter::gen_compact_code_blocks( + &cake_entity, + &WithSerde::None, + &TokenStream::new(), + &TokenStream::new(), + &DateTimeCrate::Chrono, + &None + )) + ); + assert_eq!( + comparable_file_string(include_str!("../../tests/compact_with_derives/cake_one.rs"))?, + generated_to_string(EntityWriter::gen_compact_code_blocks( + &cake_entity, + &WithSerde::None, + &bonus_derive(vec!["ts_rs::TS".into()]), + &TokenStream::new(), + &DateTimeCrate::Chrono, + &None + )) + ); + assert_eq!( + comparable_file_string(include_str!( + "../../tests/compact_with_derives/cake_multiple.rs" + ))?, + generated_to_string(EntityWriter::gen_compact_code_blocks( + &cake_entity, + &WithSerde::None, + &bonus_derive(vec!["ts_rs::TS".into(), "utoipa::ToSchema".into()]), + &TokenStream::new(), + &DateTimeCrate::Chrono, + &None + )) + ); + + // Expanded code blocks + assert_eq!( + comparable_file_string(include_str!( + "../../tests/expanded_with_derives/cake_none.rs" + ))?, + generated_to_string(EntityWriter::gen_expanded_code_blocks( + &cake_entity, + &WithSerde::None, + &TokenStream::new(), + &TokenStream::new(), + &DateTimeCrate::Chrono, + &None + )) + ); + assert_eq!( + comparable_file_string(include_str!( + "../../tests/expanded_with_derives/cake_one.rs" + ))?, + generated_to_string(EntityWriter::gen_expanded_code_blocks( + &cake_entity, + &WithSerde::None, + &bonus_derive(vec!["ts_rs::TS".into()]), + &TokenStream::new(), + &DateTimeCrate::Chrono, + &None + )) + ); + assert_eq!( + comparable_file_string(include_str!( + "../../tests/expanded_with_derives/cake_multiple.rs" + ))?, + generated_to_string(EntityWriter::gen_expanded_code_blocks( + &cake_entity, + &WithSerde::None, + &bonus_derive(vec!["ts_rs::TS".into(), "utoipa::ToSchema".into()]), + &TokenStream::new(), + &DateTimeCrate::Chrono, + &None + )) + ); Ok(()) } - #[allow(clippy::type_complexity)] - fn assert_serde_variant_results( - cake_entity: &Entity, - entity_serde_variant: &(String, WithSerde, Option), - generator: Box< - dyn Fn(&Entity, &WithSerde, &DateTimeCrate, &Option) -> Vec, - >, - ) -> io::Result<()> { - let mut reader = BufReader::new(entity_serde_variant.0.as_bytes()); + #[test] + fn test_gen_with_attributes() -> io::Result<()> { + let cake_entity = setup().get(0).unwrap().clone(); + + assert_eq!(cake_entity.get_table_name_snake_case(), "cake"); + + // Compact code blocks + assert_eq!( + comparable_file_string(include_str!( + "../../tests/compact_with_attributes/cake_none.rs" + ))?, + generated_to_string(EntityWriter::gen_compact_code_blocks( + &cake_entity, + &WithSerde::None, + &TokenStream::new(), + &TokenStream::new(), + &DateTimeCrate::Chrono, + &None + )) + ); + assert_eq!( + comparable_file_string(include_str!( + "../../tests/compact_with_attributes/cake_one.rs" + ))?, + generated_to_string(EntityWriter::gen_compact_code_blocks( + &cake_entity, + &WithSerde::None, + &TokenStream::new(), + &bonus_attributes(vec![r#"serde(rename_all = "camelCase")"#.into()]), + &DateTimeCrate::Chrono, + &None + )) + ); + assert_eq!( + comparable_file_string(include_str!( + "../../tests/compact_with_attributes/cake_multiple.rs" + ))?, + generated_to_string(EntityWriter::gen_compact_code_blocks( + &cake_entity, + &WithSerde::None, + &TokenStream::new(), + &bonus_attributes(vec![ + r#"serde(rename_all = "camelCase")"#.into(), + "ts(export)".into() + ]), + &DateTimeCrate::Chrono, + &None + )) + ); + + // Expanded code blocks + assert_eq!( + comparable_file_string(include_str!( + "../../tests/expanded_with_attributes/cake_none.rs" + ))?, + generated_to_string(EntityWriter::gen_expanded_code_blocks( + &cake_entity, + &WithSerde::None, + &TokenStream::new(), + &TokenStream::new(), + &DateTimeCrate::Chrono, + &None + )) + ); + assert_eq!( + comparable_file_string(include_str!( + "../../tests/expanded_with_attributes/cake_one.rs" + ))?, + generated_to_string(EntityWriter::gen_expanded_code_blocks( + &cake_entity, + &WithSerde::None, + &TokenStream::new(), + &bonus_attributes(vec![r#"serde(rename_all = "camelCase")"#.into()]), + &DateTimeCrate::Chrono, + &None + )) + ); + assert_eq!( + comparable_file_string(include_str!( + "../../tests/expanded_with_attributes/cake_multiple.rs" + ))?, + generated_to_string(EntityWriter::gen_expanded_code_blocks( + &cake_entity, + &WithSerde::None, + &TokenStream::new(), + &bonus_attributes(vec![ + r#"serde(rename_all = "camelCase")"#.into(), + "ts(export)".into() + ]), + &DateTimeCrate::Chrono, + &None + )) + ); + + Ok(()) + } + + fn generated_to_string(generated: Vec) -> String { + generated + .into_iter() + .fold(TokenStream::new(), |mut acc, tok| { + acc.extend(tok); + acc + }) + .to_string() + } + + fn comparable_file_string(file: &str) -> io::Result { + let mut reader = BufReader::new(file.as_bytes()); let mut lines: Vec = Vec::new(); reader.read_until(b'\n', &mut Vec::new())?; @@ -1496,19 +1773,7 @@ mod tests { } let content = lines.join(""); let expected: TokenStream = content.parse().unwrap(); - let generated = generator( - cake_entity, - &entity_serde_variant.1, - &DateTimeCrate::Chrono, - &entity_serde_variant.2, - ) - .into_iter() - .fold(TokenStream::new(), |mut acc, tok| { - acc.extend(tok); - acc - }); - assert_eq!(expected.to_string(), generated.to_string()); - Ok(()) + Ok(expected.to_string()) } } diff --git a/sea-orm-codegen/tests/compact_with_attributes/cake_multiple.rs b/sea-orm-codegen/tests/compact_with_attributes/cake_multiple.rs new file mode 100644 index 000000000..795a3b9b2 --- /dev/null +++ b/sea-orm-codegen/tests/compact_with_attributes/cake_multiple.rs @@ -0,0 +1,37 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.1.0 + +use sea_orm::entity::prelude:: * ; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[sea_orm(table_name = "cake")] +#[serde(rename_all = "camelCase")] +#[ts(export)] +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_attributes/cake_none.rs b/sea-orm-codegen/tests/compact_with_attributes/cake_none.rs new file mode 100644 index 000000000..d72ea6b21 --- /dev/null +++ b/sea-orm-codegen/tests/compact_with_attributes/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, Eq)] +#[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_attributes/cake_one.rs b/sea-orm-codegen/tests/compact_with_attributes/cake_one.rs new file mode 100644 index 000000000..11162ca1e --- /dev/null +++ b/sea-orm-codegen/tests/compact_with_attributes/cake_one.rs @@ -0,0 +1,36 @@ +//! SeaORM Entity. Generated by sea-orm-codegen 0.1.0 + +use sea_orm::entity::prelude:: * ; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[sea_orm(table_name = "cake")] +#[serde(rename_all = "camelCase")] +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_derives/cake_multiple.rs b/sea-orm-codegen/tests/compact_with_derives/cake_multiple.rs new file mode 100644 index 000000000..dd69de77c --- /dev/null +++ b/sea-orm-codegen/tests/compact_with_derives/cake_multiple.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, Eq, ts_rs::TS, utoipa::ToSchema)] +#[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_derives/cake_none.rs b/sea-orm-codegen/tests/compact_with_derives/cake_none.rs new file mode 100644 index 000000000..d72ea6b21 --- /dev/null +++ b/sea-orm-codegen/tests/compact_with_derives/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, Eq)] +#[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_derives/cake_one.rs b/sea-orm-codegen/tests/compact_with_derives/cake_one.rs new file mode 100644 index 000000000..9a4aeaba0 --- /dev/null +++ b/sea-orm-codegen/tests/compact_with_derives/cake_one.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, Eq, ts_rs::TS)] +#[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_attributes/cake_multiple.rs b/sea-orm-codegen/tests/expanded_with_attributes/cake_multiple.rs new file mode 100644 index 000000000..5c498d83c --- /dev/null +++ b/sea-orm-codegen/tests/expanded_with_attributes/cake_multiple.rs @@ -0,0 +1,79 @@ +//! 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, Eq)] +#[serde(rename_all = "camelCase")] +#[ts(export)] +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_attributes/cake_none.rs b/sea-orm-codegen/tests/expanded_with_attributes/cake_none.rs new file mode 100644 index 000000000..a540fad13 --- /dev/null +++ b/sea-orm-codegen/tests/expanded_with_attributes/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, Eq)] +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_attributes/cake_one.rs b/sea-orm-codegen/tests/expanded_with_attributes/cake_one.rs new file mode 100644 index 000000000..77da3181a --- /dev/null +++ b/sea-orm-codegen/tests/expanded_with_attributes/cake_one.rs @@ -0,0 +1,78 @@ +//! 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, Eq)] +#[serde(rename_all = "camelCase")] +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_derives/cake_multiple.rs b/sea-orm-codegen/tests/expanded_with_derives/cake_multiple.rs new file mode 100644 index 000000000..c04dfdd4d --- /dev/null +++ b/sea-orm-codegen/tests/expanded_with_derives/cake_multiple.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, Eq, ts_rs::TS, utoipa::ToSchema)] +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_derives/cake_none.rs b/sea-orm-codegen/tests/expanded_with_derives/cake_none.rs new file mode 100644 index 000000000..a540fad13 --- /dev/null +++ b/sea-orm-codegen/tests/expanded_with_derives/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, Eq)] +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_derives/cake_one.rs b/sea-orm-codegen/tests/expanded_with_derives/cake_one.rs new file mode 100644 index 000000000..a4ebdf829 --- /dev/null +++ b/sea-orm-codegen/tests/expanded_with_derives/cake_one.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, Eq, ts_rs::TS)] +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 {}