From 3659abbf0a3a04ed12cf299244b7c8b557f1af59 Mon Sep 17 00:00:00 2001 From: Billy Chan Date: Fri, 9 Jul 2021 00:18:43 +0800 Subject: [PATCH 1/4] Improve doc test --- src/entity/base_entity.rs | 239 +++++++++++++++++++++++++++++++------- 1 file changed, 200 insertions(+), 39 deletions(-) diff --git a/src/entity/base_entity.rs b/src/entity/base_entity.rs index 1717ce19..b7a758c4 100644 --- a/src/entity/base_entity.rs +++ b/src/entity/base_entity.rs @@ -51,14 +51,56 @@ pub trait EntityTrait: EntityName { /// ``` /// # #[cfg(feature = "mock")] - /// # use sea_orm::{MockDatabase, Transaction}; - /// # let db = MockDatabase::new().into_connection(); + /// # use sea_orm::{error::*, MockDatabase, Transaction, tests_cfg::*}; + /// # + /// # let db = MockDatabase::new() + /// # .append_query_results(vec![ + /// # vec![ + /// # cake::Model { + /// # id: 1, + /// # name: "New York Cheese".to_owned(), + /// # }, + /// # ], + /// # vec![ + /// # cake::Model { + /// # id: 1, + /// # name: "New York Cheese".to_owned(), + /// # }, + /// # cake::Model { + /// # id: 2, + /// # name: "Chocolate Forest".to_owned(), + /// # }, + /// # ], + /// # ]) + /// # .into_connection(); /// # /// use sea_orm::{entity::*, query::*, tests_cfg::cake}; /// - /// # async_std::task::block_on(async { - /// cake::Entity::find().one(&db).await; - /// cake::Entity::find().all(&db).await; + /// # let _: Result<(), DbErr> = async_std::task::block_on(async { + /// # + /// assert_eq!( + /// cake::Entity::find().one(&db).await?, + /// Some(cake::Model { + /// id: 1, + /// name: "New York Cheese".to_owned(), + /// }) + /// ); + /// + /// assert_eq!( + /// cake::Entity::find().all(&db).await?, + /// vec![ + /// cake::Model { + /// id: 1, + /// name: "New York Cheese".to_owned(), + /// }, + /// cake::Model { + /// id: 2, + /// name: "Chocolate Forest".to_owned(), + /// }, + /// ] + /// ); + /// # + /// # Ok(()) /// # }); /// /// assert_eq!( @@ -79,13 +121,32 @@ pub trait EntityTrait: EntityName { /// Find a model by primary key /// ``` /// # #[cfg(feature = "mock")] - /// # use sea_orm::{MockDatabase, Transaction}; - /// # let db = MockDatabase::new().into_connection(); + /// # use sea_orm::{error::*, MockDatabase, Transaction, tests_cfg::*}; + /// # + /// # let db = MockDatabase::new() + /// # .append_query_results(vec![ + /// # vec![ + /// # cake::Model { + /// # id: 11, + /// # name: "Sponge Cake".to_owned(), + /// # }, + /// # ], + /// # ]) + /// # .into_connection(); /// # /// use sea_orm::{entity::*, query::*, tests_cfg::cake}; /// - /// # async_std::task::block_on(async { - /// cake::Entity::find_by_id(11).all(&db).await; + /// # let _: Result<(), DbErr> = async_std::task::block_on(async { + /// # + /// assert_eq!( + /// cake::Entity::find_by_id(11).all(&db).await?, + /// vec![cake::Model { + /// id: 11, + /// name: "Sponge Cake".to_owned(), + /// }] + /// ); + /// # + /// # Ok(()) /// # }); /// /// assert_eq!( @@ -97,13 +158,32 @@ pub trait EntityTrait: EntityName { /// Find by composite key /// ``` /// # #[cfg(feature = "mock")] - /// # use sea_orm::{MockDatabase, Transaction}; - /// # let db = MockDatabase::new().into_connection(); + /// # use sea_orm::{error::*, MockDatabase, Transaction, tests_cfg::*}; + /// # + /// # let db = MockDatabase::new() + /// # .append_query_results(vec![ + /// # vec![ + /// # cake_filling::Model { + /// # cake_id: 2, + /// # filling_id: 3, + /// # }, + /// # ], + /// # ]) + /// # .into_connection(); /// # /// use sea_orm::{entity::*, query::*, tests_cfg::cake_filling}; /// - /// # async_std::task::block_on(async { - /// cake_filling::Entity::find_by_id((2, 3)).all(&db).await; + /// # let _: Result<(), DbErr> = async_std::task::block_on(async { + /// # + /// assert_eq!( + /// cake_filling::Entity::find_by_id((2, 3)).all(&db).await?, + /// vec![cake_filling::Model { + /// cake_id: 2, + /// filling_id: 3, + /// }] + /// ); + /// # + /// # Ok(()) /// # }); /// /// assert_eq!( @@ -137,8 +217,16 @@ pub trait EntityTrait: EntityName { /// ``` /// # #[cfg(feature = "mock")] - /// # use sea_orm::{MockDatabase, Transaction}; - /// # let db = MockDatabase::new().into_connection(); + /// # use sea_orm::{error::*, MockDatabase, MockExecResult, Transaction, tests_cfg::*}; + /// # + /// # let db = MockDatabase::new() + /// # .append_exec_results(vec![ + /// # MockExecResult { + /// # last_insert_id: 15, + /// # rows_affected: 1, + /// # }, + /// # ]) + /// # .into_connection(); /// # /// use sea_orm::{entity::*, query::*, tests_cfg::cake}; /// @@ -147,8 +235,14 @@ pub trait EntityTrait: EntityName { /// ..Default::default() /// }; /// - /// # async_std::task::block_on(async { - /// cake::Entity::insert(apple).exec(&db).await; + /// # let _: Result<(), DbErr> = async_std::task::block_on(async { + /// # + /// let insert_result = cake::Entity::insert(apple).exec(&db).await?; + /// + /// assert_eq!(insert_result.last_insert_id, 15); + /// // assert_eq!(insert_result.rows_affected, 1); + /// # + /// # Ok(()) /// # }); /// /// assert_eq!( @@ -166,8 +260,16 @@ pub trait EntityTrait: EntityName { /// ``` /// # #[cfg(feature = "mock")] - /// # use sea_orm::{MockDatabase, Transaction}; - /// # let db = MockDatabase::new().into_connection(); + /// # use sea_orm::{error::*, MockDatabase, MockExecResult, Transaction, tests_cfg::*}; + /// # + /// # let db = MockDatabase::new() + /// # .append_exec_results(vec![ + /// # MockExecResult { + /// # last_insert_id: 28, + /// # rows_affected: 2, + /// # }, + /// # ]) + /// # .into_connection(); /// # /// use sea_orm::{entity::*, query::*, tests_cfg::cake}; /// @@ -180,8 +282,14 @@ pub trait EntityTrait: EntityName { /// ..Default::default() /// }; /// - /// # async_std::task::block_on(async { - /// cake::Entity::insert_many(vec![apple, orange]).exec(&db).await; + /// # let _: Result<(), DbErr> = async_std::task::block_on(async { + /// # + /// let insert_result = cake::Entity::insert_many(vec![apple, orange]).exec(&db).await?; + /// + /// assert_eq!(insert_result.last_insert_id, 28); + /// // assert_eq!(insert_result.rows_affected, 2); + /// # + /// # Ok(()) /// # }); /// /// assert_eq!( @@ -201,8 +309,16 @@ pub trait EntityTrait: EntityName { /// ``` /// # #[cfg(feature = "mock")] - /// # use sea_orm::{MockDatabase, Transaction}; - /// # let db = MockDatabase::new().into_connection(); + /// # use sea_orm::{error::*, MockDatabase, MockExecResult, Transaction, tests_cfg::*}; + /// # + /// # let db = MockDatabase::new() + /// # .append_exec_results(vec![ + /// # MockExecResult { + /// # last_insert_id: 0, + /// # rows_affected: 1, + /// # }, + /// # ]) + /// # .into_connection(); /// # /// use sea_orm::{entity::*, query::*, tests_cfg::fruit}; /// @@ -212,8 +328,14 @@ pub trait EntityTrait: EntityName { /// ..Default::default() /// }; /// - /// # async_std::task::block_on(async { - /// fruit::Entity::update(orange).exec(&db).await; + /// # let _: Result<(), DbErr> = async_std::task::block_on(async { + /// # + /// assert_eq!( + /// fruit::Entity::update(orange.clone()).exec(&db).await?, // Clone here because we need to assert_eq + /// orange + /// ); + /// # + /// # Ok(()) /// # }); /// /// assert_eq!( @@ -231,17 +353,30 @@ pub trait EntityTrait: EntityName { /// ``` /// # #[cfg(feature = "mock")] - /// # use sea_orm::{MockDatabase, Transaction}; - /// # let db = MockDatabase::new().into_connection(); + /// # use sea_orm::{error::*, MockDatabase, MockExecResult, Transaction, tests_cfg::*}; + /// # + /// # let db = MockDatabase::new() + /// # .append_exec_results(vec![ + /// # MockExecResult { + /// # last_insert_id: 0, + /// # rows_affected: 5, + /// # }, + /// # ]) + /// # .into_connection(); /// # /// use sea_orm::{entity::*, query::*, tests_cfg::fruit, sea_query::{Expr, Value}}; /// - /// # async_std::task::block_on(async { - /// fruit::Entity::update_many() + /// # let _: Result<(), DbErr> = async_std::task::block_on(async { + /// # + /// let update_result = fruit::Entity::update_many() /// .col_expr(fruit::Column::CakeId, Expr::value(Value::Null)) /// .filter(fruit::Column::Name.contains("Apple")) /// .exec(&db) - /// .await; + /// .await?; + /// + /// assert_eq!(update_result.rows_affected, 5); + /// # + /// # Ok(()) /// # }); /// /// assert_eq!( @@ -256,8 +391,16 @@ pub trait EntityTrait: EntityName { /// ``` /// # #[cfg(feature = "mock")] - /// # use sea_orm::{MockDatabase, Transaction}; - /// # let db = MockDatabase::new().into_connection(); + /// # use sea_orm::{error::*, MockDatabase, MockExecResult, Transaction, tests_cfg::*}; + /// # + /// # let db = MockDatabase::new() + /// # .append_exec_results(vec![ + /// # MockExecResult { + /// # last_insert_id: 0, + /// # rows_affected: 1, + /// # }, + /// # ]) + /// # .into_connection(); /// # /// use sea_orm::{entity::*, query::*, tests_cfg::fruit}; /// @@ -266,8 +409,13 @@ pub trait EntityTrait: EntityName { /// ..Default::default() /// }; /// - /// # async_std::task::block_on(async { - /// fruit::Entity::delete(orange).exec(&db).await; + /// # let _: Result<(), DbErr> = async_std::task::block_on(async { + /// # + /// let delete_result = fruit::Entity::delete(orange).exec(&db).await?; + /// + /// assert_eq!(delete_result.rows_affected, 1); + /// # + /// # Ok(()) /// # }); /// /// assert_eq!( @@ -285,16 +433,29 @@ pub trait EntityTrait: EntityName { /// ``` /// # #[cfg(feature = "mock")] - /// # use sea_orm::{MockDatabase, Transaction}; - /// # let db = MockDatabase::new().into_connection(); + /// # use sea_orm::{error::*, MockDatabase, MockExecResult, Transaction, tests_cfg::*}; + /// # + /// # let db = MockDatabase::new() + /// # .append_exec_results(vec![ + /// # MockExecResult { + /// # last_insert_id: 0, + /// # rows_affected: 5, + /// # }, + /// # ]) + /// # .into_connection(); /// # /// use sea_orm::{entity::*, query::*, tests_cfg::fruit}; /// - /// # async_std::task::block_on(async { - /// fruit::Entity::delete_many() + /// # let _: Result<(), DbErr> = async_std::task::block_on(async { + /// # + /// let delete_result = fruit::Entity::delete_many() /// .filter(fruit::Column::Name.contains("Apple")) /// .exec(&db) - /// .await; + /// .await?; + /// + /// assert_eq!(delete_result.rows_affected, 5); + /// # + /// # Ok(()) /// # }); /// /// assert_eq!( From c73e10cc5918a57d7ace811843271a0087a7190c Mon Sep 17 00:00:00 2001 From: Billy Chan Date: Fri, 9 Jul 2021 12:52:28 +0800 Subject: [PATCH 2/4] Fix clippy warming --- src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index ae71656e..3e49958b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -177,9 +177,9 @@ //! Licensed under either of //! //! - Apache License, Version 2.0 -//! ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) +//! ([LICENSE-APACHE](LICENSE-APACHE) or ) //! - MIT license -//! ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) +//! ([LICENSE-MIT](LICENSE-MIT) or ) //! //! at your option. //! From ce32967a95cff0dc6e66060be650284e1e10d3d8 Mon Sep 17 00:00:00 2001 From: Billy Chan Date: Mon, 12 Jul 2021 11:12:32 +0800 Subject: [PATCH 3/4] Add base_entity doc --- src/entity/base_entity.rs | 56 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/src/entity/base_entity.rs b/src/entity/base_entity.rs index b7a758c4..bec0c854 100644 --- a/src/entity/base_entity.rs +++ b/src/entity/base_entity.rs @@ -18,7 +18,18 @@ pub trait EntityName: IdenStatic + Default { Self::table_name(self) } } - +/// Each table in database correspond to a Entity implemented [`EntityTrait`]. +/// +/// This trait provides an API for you to inspect it's properties +/// - Column (implemented [`ColumnTrait`]) +/// - Relation (implemented [`RelationTrait`]) +/// - Primary Key (implemented [`PrimaryKeyTrait`] and [`PrimaryKeyToColumn`]) +/// +/// This trait also provides an API for CRUD actions +/// - Select: `find`, `find_*` +/// - Insert: `insert`, `insert_*` +/// - Update: `update`, `update_*` +/// - Delete: `delete`, `delete_*` pub trait EntityTrait: EntityName { type Model: ModelTrait + FromQueryResult; @@ -49,6 +60,14 @@ pub trait EntityTrait: EntityName { RelationBuilder::from_rel(RelationType::HasMany, R::to().rev()) } + /// Construct select statement to find one / all models + /// + /// - To select columns, join tables and group by expressions, see [`QuerySelect`](crate::query::QuerySelect) + /// - To apply where conditions / filters, see [`QueryFilter`](crate::query::QueryFilter) + /// - To apply order by expressions, see [`QueryOrder`](crate::query::QueryOrder) + /// + /// # Example + /// /// ``` /// # #[cfg(feature = "mock")] /// # use sea_orm::{error::*, MockDatabase, Transaction, tests_cfg::*}; @@ -119,6 +138,9 @@ pub trait EntityTrait: EntityName { } /// Find a model by primary key + /// + /// # Example + /// /// ``` /// # #[cfg(feature = "mock")] /// # use sea_orm::{error::*, MockDatabase, Transaction, tests_cfg::*}; @@ -215,6 +237,10 @@ pub trait EntityTrait: EntityName { select } + /// Insert an model into database + /// + /// # Example + /// /// ``` /// # #[cfg(feature = "mock")] /// # use sea_orm::{error::*, MockDatabase, MockExecResult, Transaction, tests_cfg::*}; @@ -258,6 +284,10 @@ pub trait EntityTrait: EntityName { Insert::one(model) } + /// Insert many models into database + /// + /// # Example + /// /// ``` /// # #[cfg(feature = "mock")] /// # use sea_orm::{error::*, MockDatabase, MockExecResult, Transaction, tests_cfg::*}; @@ -307,6 +337,12 @@ pub trait EntityTrait: EntityName { Insert::many(models) } + /// Update an model in database + /// + /// - To apply where conditions / filters, see [`QueryFilter`](crate::query::QueryFilter) + /// + /// # Example + /// /// ``` /// # #[cfg(feature = "mock")] /// # use sea_orm::{error::*, MockDatabase, MockExecResult, Transaction, tests_cfg::*}; @@ -351,6 +387,12 @@ pub trait EntityTrait: EntityName { Update::one(model) } + /// Update many models in database + /// + /// - To apply where conditions / filters, see [`QueryFilter`](crate::query::QueryFilter) + /// + /// # Example + /// /// ``` /// # #[cfg(feature = "mock")] /// # use sea_orm::{error::*, MockDatabase, MockExecResult, Transaction, tests_cfg::*}; @@ -389,6 +431,12 @@ pub trait EntityTrait: EntityName { Update::many(Self::default()) } + /// Delete an model from database + /// + /// - To apply where conditions / filters, see [`QueryFilter`](crate::query::QueryFilter) + /// + /// # Example + /// /// ``` /// # #[cfg(feature = "mock")] /// # use sea_orm::{error::*, MockDatabase, MockExecResult, Transaction, tests_cfg::*}; @@ -431,6 +479,12 @@ pub trait EntityTrait: EntityName { Delete::one(model) } + /// Delete many models from database + /// + /// - To apply where conditions / filters, see [`QueryFilter`](crate::query::QueryFilter) + /// + /// # Example + /// /// ``` /// # #[cfg(feature = "mock")] /// # use sea_orm::{error::*, MockDatabase, MockExecResult, Transaction, tests_cfg::*}; From b09aed3ff1157c039791a940d73f4fcfe888372b Mon Sep 17 00:00:00 2001 From: Billy Chan Date: Mon, 12 Jul 2021 11:45:20 +0800 Subject: [PATCH 4/4] Add more doc --- src/entity/active_model.rs | 1 + src/entity/column.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/src/entity/active_model.rs b/src/entity/active_model.rs index 5ab7be19..8eb26504 100644 --- a/src/entity/active_model.rs +++ b/src/entity/active_model.rs @@ -243,6 +243,7 @@ where exec.await } +/// Delete an active model by its primary key pub async fn delete_active_model( mut am: A, db: &DatabaseConnection, diff --git a/src/entity/column.rs b/src/entity/column.rs index de98c0d7..d6580e8f 100644 --- a/src/entity/column.rs +++ b/src/entity/column.rs @@ -66,6 +66,7 @@ macro_rules! bind_vec_func { } // LINT: when the operand value does not match column type +/// Wrapper of the identically named method in [`sea_query::Expr`] pub trait ColumnTrait: IdenStatic + Iterable { type EntityName: EntityName;