1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
pub mod question;
pub mod topic_tag;

use sea_orm::prelude::async_trait::async_trait;
use sea_orm::InsertResult;
use sea_orm::{prelude::*, sea_query::OnConflict};
use serde::de::DeserializeOwned;
use serde::Serialize;

use crate::errors::AppResult;

#[async_trait]
pub trait ModelUtils: Serialize + std::marker::Sized {
    type ActiveModel: ActiveModelTrait<Entity = Self::Entity>
        + std::marker::Send
        + std::convert::From<Self::Model>;
    type Entity: EntityTrait;
    type Model: ModelTrait + DeserializeOwned;

    fn to_model(&self) -> AppResult<Self::Model> {
        let p = serde_json::to_string(self)?;
        Ok(serde_json::from_str(p.as_str())?)
    }

    async fn to_db(&self, db: &DatabaseConnection) -> AppResult<InsertResult<Self::ActiveModel>> {
        let m: Self::ActiveModel = self.get_active_model()?;
        Ok(Self::Entity::insert(m)
            .on_conflict(Self::on_conflict())
            .exec(db)
            .await?)
    }

    async fn post_multi_insert(_db: &DatabaseConnection, _objects: Vec<Self>) -> AppResult<()> {
        Ok(())
    }

    async fn multi_insert(db: &DatabaseConnection, objects: Vec<Self>) -> AppResult<()> {
        let mut v = vec![];
        for obj in objects.iter() {
            let k: Self::ActiveModel = obj.get_active_model()?;
            v.push(k);
        }
        if !v.is_empty() {
            Self::Entity::insert_many(v)
                .on_conflict(Self::on_conflict())
                .exec(db)
                .await?;
        }
        Self::post_multi_insert(db, objects).await?;
        Ok(())
    }

    fn get_active_model(&self) -> AppResult<Self::ActiveModel> {
        let model = self.to_model()?;
        Ok(model.into())
    }

    fn on_conflict() -> OnConflict;
}