Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

0.3.0 Docs - 1 #11

Merged
merged 5 commits into from
Oct 19, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions SeaORM/docs/01-index.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,12 @@

6.5 [More joins](/docs/advanced-query/more-join)

6.6 [Transaction](/docs/advanced-query/transaction)

6.7 [Streaming](/docs/advanced-query/streaming)

6.8 [Custom Active Model](/docs/advanced-query/custom-active-model)

7. Internal Design

7.1 [Traits and Types](/docs/internal-design/trait-and-type)
Expand Down
35 changes: 25 additions & 10 deletions SeaORM/docs/03-generate-entity/03-expanded-entity-structure.md
Original file line number Diff line number Diff line change
Expand Up @@ -153,22 +153,37 @@ Handler for different actions on an `ActiveModel`.
impl ActiveModelBehavior for ActiveModel {
/// Create a new ActiveModel with default values. Also used by `Default::default()`.
fn new() -> Self {
<Self as ActiveModelTrait>::default()
Self {
uuid: Set(Uuid::new_v4()),
..ActiveModelTrait::default()
}
}

/// Will be triggered before insert / update
fn before_save(self, insert: bool) -> Result<Self, DbErr> {
if self.price.as_ref() <= &0.0 {
Err(DbErr::Custom(format!(
"[before_save] Invalid Price, insert: {}",
insert
)))
} else {
Ok(self)
}
}

/// Will be called before saving
fn before_save(self) -> Self {
self
/// Will be triggered after insert / update
fn after_save(self, insert: bool) -> Result<Self, DbErr> {
Ok(self)
}

/// Will be called after saving
fn after_save(self) -> Self {
self
/// Will be triggered before delete
fn before_delete(self) -> Result<Self, DbErr> {
Ok(self)
}

/// Will be called before deleting
fn before_delete(self) -> Self {
self
/// Will be triggered after delete
fn after_delete(self) -> Result<Self, DbErr> {
Ok(self)
}
}
```
Expand Down
13 changes: 12 additions & 1 deletion SeaORM/docs/04-basic-crud/02-insert.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,17 @@ assert_eq!(active_model.name, ActiveValue::unchanged("Cheese Cake".to_owned()));

## Insert One

Insert single active model and get inserted `ActiveModel`.

```rust
let pear = fruit::ActiveModel {
name: Set("Pear".to_owned()),
..Default::default() // all other attributes are `Unset`
};

let res: fruit::ActiveModel = pear.insert(db).await?;
```

Insert single active model and get the last insert id.

```rust
Expand All @@ -42,7 +53,7 @@ let pear = fruit::ActiveModel {
..Default::default() // all other attributes are `Unset`
};

let res: InsertResult = pear.insert(db).await?;
let res: InsertResult = fruit::Entity::insert(pear).exec(db).await?;
assert_eq!(res.last_insert_id, 28)
```

Expand Down
58 changes: 58 additions & 0 deletions SeaORM/docs/07-advanced-query/06-transaction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# Transaction

You can perform atomic operations inside transaction. There are two transaction APIs available to you.

## `Closure` style

Transaction will be committed if the closure returned `Ok`, rollbacked if `Err`.

```rust
db.transaction::<_, _, DbErr>(|txn| {
Box::pin(async move {
bakery::ActiveModel {
name: Set("SeaSide Bakery".to_owned()),
profit_margin: Set(10.4),
..Default::default()
}
.save(txn)
.await?;

bakery::ActiveModel {
name: Set("Top Bakery".to_owned()),
profit_margin: Set(15.0),
..Default::default()
}
.save(txn)
.await?;

Ok(())
})
})
.await;
```

## `Begin` ... `commit` / `rollback` style

`Begin` the transaction followed by `commit` or `rollback`. If `txn` goes out of scope, it'd automatically rollback.

```rust
let txn = db.begin().await?;

bakery::ActiveModel {
name: Set("SeaSide Bakery".to_owned()),
profit_margin: Set(10.4),
..Default::default()
}
.save(&txn)
.await?;

bakery::ActiveModel {
name: Set("Top Bakery".to_owned()),
profit_margin: Set(15.0),
..Default::default()
}
.save(&txn)
.await?;

txn.commit().await?;
```
34 changes: 34 additions & 0 deletions SeaORM/docs/07-advanced-query/07-streaming.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Streaming

Use async stream on any `Select` for memory efficiency.

```rust
// Stream all fruits
let mut stream = Fruit::find().stream(db).await?;

while let Some(item) = stream.try_next().await? {
let item: fruit::ActiveModel = item.into();
// do something with item
}
```

```rust
// Stream all fruits with name contains character "a"
let mut stream = Fruit::find()
.filter(fruit::Column::Name.contains("a"))
.order_by_asc(fruit::Column::Name)
.stream(db)
.await?;
```

Note that stream will persists the connection from connection pool until it gets dropped.

```rust
{
// 3 connections are used
let _ = Fruit::find().stream(db).await?;
let _ = Fruit::find().stream(db).await?;
let _ = Fruit::find().stream(db).await?;
}
// All streams are dropped and connections are returned to connection pool
```
87 changes: 87 additions & 0 deletions SeaORM/docs/07-advanced-query/08-custom-active-model.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# Custom Active Model

A derive macro `DeriveIntoActiveModel` for implementing `IntoActiveModel` on structs. This is useful for creating your own struct with only partial fields of a model, for example an insert struct, or update struct.

`IntoActiveValue` trait allows converting `Option<T>` into `ActiveValue<T>` automatically.

```rust
// Define regular model as usual
#[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
#[sea_orm(table_name = "fruit")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
pub name: String,
pub cake_id: Option<i32>,
}
```

Create a new struct with some fields omitted.

```rust
#[derive(DeriveIntoActiveModel)]
pub struct NewFruit {
// id is omitted
pub name: String,
// it is required as opposed to optional in Model
pub cake_id: i32,
}

assert_eq!(
NewFruit {
name: "Apple".to_owned(),
cake_id: 1,
}
.into_active_model(),
fruit::ActiveModel {
id: Unset(None),
name: Set("Apple".to_owned()),
cake_id: Set(Some(1)),
}
);
```

`Option<Option<T>>` allows for `Some(None)` to update the column to be NULL.

```rust
#[derive(DeriveIntoActiveModel)]
pub struct UpdateFruit {
pub cake_id: Option<Option<i32>>,
}

assert_eq!(
UpdateFruit {
cake_id: Some(Some(1)),
}
.into_active_model(),
fruit::ActiveModel {
id: Unset(None),
name: Unset(None),
cake_id: Set(Some(1)),
}
);

assert_eq!(
UpdateFruit {
cake_id: Some(None),
}
.into_active_model(),
fruit::ActiveModel {
id: Unset(None),
name: Unset(None),
cake_id: Set(None),
}
);

assert_eq!(
UpdateFruit {
cake_id: None,
}
.into_active_model(),
fruit::ActiveModel {
id: Unset(None),
name: Unset(None),
cake_id: Unset(None),
}
);
```