From e0023611a2eed72b1885a5f2a3b7e594f05c4482 Mon Sep 17 00:00:00 2001 From: Charles Chege Date: Sat, 30 Oct 2021 11:15:43 +0300 Subject: [PATCH] Improve documentation for the drivers and the entity Provide module level code example on how to create an Entity, Model, ActiveModel, Column and PrimaryKey --- src/driver/sqlx_mysql.rs | 2 +- src/driver/sqlx_sqlite.rs | 4 +- src/entity/active_model.rs | 38 +++++++++++- src/entity/base_entity.rs | 1 + src/entity/mod.rs | 122 +++++++++++++++++++++++++++++++++++++ src/entity/primary_key.rs | 33 +++++++++- 6 files changed, 194 insertions(+), 6 deletions(-) diff --git a/src/driver/sqlx_mysql.rs b/src/driver/sqlx_mysql.rs index a861b8df..b2b89c68 100644 --- a/src/driver/sqlx_mysql.rs +++ b/src/driver/sqlx_mysql.rs @@ -126,7 +126,7 @@ impl SqlxMySqlPoolConnection { } } - /// Bundle a set of SQL statements that execute together. + /// Bundle a set of SQL statements that execute together. pub async fn begin(&self) -> Result { if let Ok(conn) = self.pool.acquire().await { DatabaseTransaction::new_mysql(conn).await diff --git a/src/driver/sqlx_sqlite.rs b/src/driver/sqlx_sqlite.rs index 4139a0f9..f9e10712 100644 --- a/src/driver/sqlx_sqlite.rs +++ b/src/driver/sqlx_sqlite.rs @@ -30,7 +30,7 @@ impl SqlxSqliteConnector { pub fn accepts(string: &str) -> bool { string.starts_with("sqlite:") && string.parse::().is_ok() } - + /// Add configuration options for the SQLite database pub async fn connect(options: ConnectOptions) -> Result { let mut opt = options @@ -129,7 +129,7 @@ impl SqlxSqlitePoolConnection { } } - /// Bundle a set of SQL statements that execute together. + /// Bundle a set of SQL statements that execute together. pub async fn begin(&self) -> Result { if let Ok(conn) = self.pool.acquire().await { DatabaseTransaction::new_sqlite(conn).await diff --git a/src/entity/active_model.rs b/src/entity/active_model.rs index 7945d6dc..57e2569d 100644 --- a/src/entity/active_model.rs +++ b/src/entity/active_model.rs @@ -55,7 +55,27 @@ where ActiveValue::unchanged(value) } -/// Enforces a set of constraints on any type performing an Create, Update or Delete operation +/// Enforces a set of constraints on any type performing an Create, Update or Delete operation. +/// The type must also implement the [EntityTrait]. +/// #### Example +/// ``` +/// 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, DeriveActiveModel)] +/// pub struct Model { +/// pub id: i32, +/// pub name: Option , +/// } +/// ``` #[async_trait] pub trait ActiveModelTrait: Clone + Debug { /// Enforce the type to the constraints of the [EntityTrait] @@ -186,7 +206,21 @@ pub trait ActiveModelTrait: Clone + Debug { } /// Enforce a set of constraints to a override the ActiveModel behavior -/// Behaviors for users to override +/// Behaviors for users to override. +/// The type must also implement the [ActiveModelTrait] +/// +/// ### Example +/// ``` +/// /// Derive the active +/// #[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel)] +/// pub struct Model { +/// pub id: i32, +/// pub name: String, +/// pub cake_id: Option, +/// } +/// ``` +/// impl ActiveModelBehavior for ActiveModel {} +/// #[allow(unused_variables)] pub trait ActiveModelBehavior: ActiveModelTrait { /// Create a new ActiveModel with default values. Also used by `Default::default()`. diff --git a/src/entity/base_entity.rs b/src/entity/base_entity.rs index 4d3e1d87..0fe504dd 100644 --- a/src/entity/base_entity.rs +++ b/src/entity/base_entity.rs @@ -37,6 +37,7 @@ pub trait EntityName: IdenStatic + Default { } } +/// FIXME Add docs for manual impl /// An Entity implementing `EntityTrait` represents a table in a database. /// /// This trait provides an API for you to inspect it's properties diff --git a/src/entity/mod.rs b/src/entity/mod.rs index f78795dc..8b4fe6f8 100644 --- a/src/entity/mod.rs +++ b/src/entity/mod.rs @@ -1,3 +1,125 @@ +//! This modules contains types and traits for an Entity, ActiveMode, Model, PrimaryKey, ForeignKey and Relations. +//! +//! // An Entity +//! A unit struct implements [EntityTrait](crate::EntityTrait) representing a table in the database. +//! +//! This trait contains the properties of an entity including +//! +//! Table Name (implemented EntityName) +//! 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_* +//! +//! #### Example for creating an Entity, Model and ActiveModel +//! ``` +//! use sea_orm::entity::prelude::*; +//! +//! // Use [DeriveEntity] to derive the EntityTrait automatically +//! #[derive(Copy, Clone, Default, Debug, DeriveEntity)] +//! pub struct Entity; +//! +//! /// The [EntityName] describes the name of a table +//! impl EntityName for Entity { +//! fn table_name(&self) -> &str { +//! "cake" +//! } +//! } +//! +//! // Create a Model for the Entity through [DeriveModel]. +//! // The `Model` handles `READ` operations on a table in a database. +//! // The [DeriveActiveModel] creates a way to perform `CREATE` , `READ` and `UPDATE` operations +//! // in a database +//! +//! #[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel)] +//! pub struct Model { +//! pub id: i32, +//! pub name: Option , +//! } +//! +//! // Use the [DeriveColumn] to create a Column for an the table called Entity +//! // The [EnumIter] which creates a new type that iterates of the variants of a Column. +//! #[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)] +//! pub enum Column { +//! Id, +//! Name, +//! } +//! +//! // Create a PrimaryKey for the Entity using the [PrimaryKeyTrait] +//! // The [EnumIter] which creates a new type that iterates of the variants of a PrimaryKey. +//! #[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)] +//! pub enum PrimaryKey { +//! Id, +//! } +//! +//! // Or implement the [PrimaryKeyTrait] manually instead of using the macro [DerivePrimaryKey] +//! impl PrimaryKeyTrait for PrimaryKey { +//! type ValueType = i32; +//! +//! fn auto_increment() -> bool { +//! true +//! } +//! } +//! +//! // Create a Relation for the Entity +//! #[derive(Copy, Clone, Debug, EnumIter)] +//! #[sea_orm( +//! // The relation belongs to `Entity` type +//! belongs_to = "Entity", +//! from = "Column::FruitId", +//! to = "Column::Id" +//! )] +//! pub enum Relation { +//! Fruit, +//! } +//! +//! // Create the properties of a Column in an Entity ensuring that calling +//! // Column::def() yields a Column definition as defined in [ColumnDef] +//! impl ColumnTrait for Column { +//! type EntityName = Entity; +//! fn def(&self) -> ColumnDef { +//! match self { +//! Self::Id => ColumnType::Integer.def(), +//! Self::Name => ColumnType::Text.def().null(), +//! } +//! } +//! } +//! +//! // Implement the set of constraints for creating a Relation as defined in the [RelationTrait] +//! 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()) +//! } +//! } +//! +//! // Implement user defined operations for CREATE, UPDATE and DELETE operations +//! // to create an ActiveModel using the [ActiveModelBehavior] +//! impl ActiveModelBehavior for ActiveModel {} +//! ``` + mod active_model; mod base_entity; mod column; diff --git a/src/entity/primary_key.rs b/src/entity/primary_key.rs index 17015fa4..39969888 100644 --- a/src/entity/primary_key.rs +++ b/src/entity/primary_key.rs @@ -4,7 +4,38 @@ use sea_query::{FromValueTuple, IntoValueTuple}; use std::fmt::Debug; //LINT: composite primary key cannot auto increment -/// A set of constraints to be used to define a Primary Key +/// A set of constraints to be used to define a Primary Key. +/// +/// A primary key can be derived manually +/// +/// ### Example +/// ``` +/// use sea_orm::entity::prelude::*; +/// +/// #[derive(Copy, Clone, Debug, EnumIter)] +/// pub enum PrimaryKey { +/// Id, +/// } +/// impl PrimaryKeyTrait for PrimaryKey { +/// type ValueType = i32; +/// +/// fn auto_increment() -> bool { +/// true +/// } +/// } +/// ``` +/// +/// Alternatively, use derive macros to automatically implement the trait for a Primary Key +/// +/// ### Example +/// ``` +/// use sea_orm::entity::prelude::*; +/// +/// #[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)] +/// pub enum PrimaryKey { +/// Id, +/// } +/// ``` pub trait PrimaryKeyTrait: IdenStatic + Iterable { #[allow(missing_docs)] type ValueType: Sized