【Day 23】ブログ一覧を取得し、表示する - SeaORM

## はじめに

![スライド24.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985550/692fc214-724c-35b3-3200-f522f06983f5.png)
---

**2023年アドベントカレンダー23日目**です。

https://qiita.com/advent-calendar/2023/life-sync-app

本日は昨日に引き続き、「ユーザーはトップページでブログタイトルの一覧を見ることができる」を進めていきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985550/6eb0ef2a-c7f4-7a75-add7-a866d28b214d.png)

昨日はDriver以外の実装をしたので、今日はDriverの実装を進めていきます。

## SeaORM

### SeaORMとは

SeaORMとは、RustのORMです。
最近SeaORMをよく見る気がするので、使ってみようと思います

https://www.sea-ql.org/SeaORM/

## 依存関係の追加

公式の例ではこのようになっています。

```toml:Cargo.toml
sea-orm = { version = "0.12", features = [ <DATABASE_DRIVER>, <ASYNC_RUNTIME>, "macros" ] }
```

DBはpostgresqlを選んでいるので、`<DATABASE_DRIVER>`には`sqlx-postgres`を選択し、
`<ASYNC_RUNTIME>`には`runtime-async-std-native-tls`を設定します。

```toml:Cargo.toml
sea-orm = { version = "^0.12.0", features = [ "sqlx-postgres", "runtime-async-std-native-tls", "macros", "mock" ] }
```
このようになりました。

## Database Connection

次にDatabaseと接続します。

```rust:blog/src/driver/blog_driver.rs
#[mry::mry]
pub async fn get() -> EyreResult<BlogsJson> {
    let db_url = "postgres://blog:blog@localhost:5432/blog";
    let db: DatabaseConnection = Database::connect(db_url).await?;
}
```

このように設定します。
`db`だけ別にしたり、`db_url`を環境変数にしたりということはするべきでしょう。

## Generate Entities With `sea-orm-cli`

まず、`sea-orm-cli`をインストールします。

```bash
cargo install sea-orm-cli
```

インストールが完了したら、エンティティを作成しましょう！

:::note warn
実行前にDBを起動するのを忘れないようにしましょう
Postgresqlに関しては[Day 18](https://qiita.com/maaaashi/items/5ac7cb6f8791f00b4972)で作成しています
:::

```bash
sea-orm-cli generate entity -u postgres://blog:blog@localhost/blog -o ./blog/src/entity
```

実行すると以下のようなファイルが作成されます

```
blog/src/entiry
├── blog.rs
├── mod.rs
└── prelude.rs
```

```rust:mod.rs
//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.6

pub mod prelude;

pub mod blog;
```

```rust:prelude.rs
//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.6

pub use super::blog::Entity as Blog;
```

```rust:blog.rs
//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.6

use sea_orm::entity::prelude::*;

#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)]
#[sea_orm(table_name = "blog")]
pub struct Model {
    #[sea_orm(primary_key, auto_increment = false)]
    pub id: Uuid,
    pub title: String,
    pub author: String,
    #[sea_orm(column_type = "Text")]
    pub body: String,
    pub created_at: String,
}

#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {}

impl ActiveModelBehavior for ActiveModel {}
```

## Driver実装

作成したEntityを使って、DBから、ブログデータの取得をします。

```rust:blog/src/driver/blog_driver.rs
use crate::entity::blog::Entity as BlogEntity;

#[mry::mry]
pub async fn get() -> EyreResult<BlogsJson> {
    let db_url = "postgres://blog:blog@localhost:5432/blog";
    let db: DatabaseConnection = Database::connect(db_url).await?;
    let blogs = BlogEntity::find().all(&db).await.unwrap();

    let blogs_json = BlogsJson {
        blogs: blogs
            .into_iter()
            .map(|blog| BlogJson {
                id: blog.id.to_string(),
                title: blog.title.to_string(),
                author: blog.author.to_string(),
                body: blog.body.to_string(),
                created_at: blog.created_at.to_string(),
            })
            .collect(),
    };
    Ok(blogs_json)
}
```

これで昨日と合わせて`Rest`, `Usecase`, `Gateway`, `Driver`のすべての実装が終わりました

[【Day 19】](https://qiita.com/maaaashi/items/25817610bb1175d48599)で作成したE2Eテストを流してみます

:::note
参考として、テストスペックファイルを載せておきます。
```markdown:e2e/specs/blog.spec
# Blog E2E

## Get Blogs

* URL"http://localhost:3000/blogs"にGETリクエストを送る
* レスポンスステータスコードが"200"である
* レスポンス内JsonBodyの"blogs[0].id"が文字列の"123e4567-e89b-12d3-a456-426614174000"である
* レスポンス内JsonBodyの"blogs[0].title"が文字列の"カフェの隅で見つけた幸せ：私のお気に入りの隠れ家"である
* レスポンス内JsonBodyの"blogs[0].author"が文字列の"田中太郎"である
* レスポンス内JsonBodyの"blogs[0].body"が文字列の"ブログの本文"である
* レスポンス内JsonBodyの"blogs[0].createdAt"が文字列の"2023-12-09 09:00:00"である
```
:::



```bash
$ gauge run specs
# Blog E2E
  ## Get Blogs   ✔ ✔ ✔ ✔ ✔ ✔ ✔
```


すべて通りました👍
無事DBからデータを取得し、Rest層がJSONデータを返しているようです👍

明日、明後日でアドベントカレンダーも終了を迎えます。

LifeSyncのアプリケーションとしてはトップページでブログの一覧を見せることまでしか機能の作りこみはできていませんが、残りの2日間を使ってK8s環境でWeb, Bff, API, DBのすべてが起動するようにしていこうと思います👍