はじめに
2023年アドベントカレンダー23日目です。
本日は昨日に引き続き、「ユーザーはトップページでブログタイトルの一覧を見ることができる」を進めていきます。
昨日はDriver以外の実装をしたので、今日はDriverの実装を進めていきます。
SeaORM
SeaORMとは
SeaORMとは、RustのORMです。
最近SeaORMをよく見る気がするので、使ってみようと思います
依存関係の追加
公式の例ではこのようになっています。
sea-orm = { version = "0.12", features = [ <DATABASE_DRIVER>, <ASYNC_RUNTIME>, "macros" ] }
DBはpostgresqlを選んでいるので、<DATABASE_DRIVER>
にはsqlx-postgres
を選択し、
<ASYNC_RUNTIME>
にはruntime-async-std-native-tls
を設定します。
sea-orm = { version = "^0.12.0", features = [ "sqlx-postgres", "runtime-async-std-native-tls", "macros", "mock" ] }
このようになりました。
Database Connection
次にDatabaseと接続します。
#[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
をインストールします。
cargo install sea-orm-cli
インストールが完了したら、エンティティを作成しましょう!
実行前にDBを起動するのを忘れないようにしましょう
Postgresqlに関してはDay 18で作成しています
sea-orm-cli generate entity -u postgres://blog:blog@localhost/blog -o ./blog/src/entity
実行すると以下のようなファイルが作成されます
blog/src/entiry
├── blog.rs
├── mod.rs
└── prelude.rs
//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.6
pub mod prelude;
pub mod blog;
//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.6
pub use super::blog::Entity as Blog;
//! `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から、ブログデータの取得をします。
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】で作成したE2Eテストを流してみます
参考として、テストスペックファイルを載せておきます。
# 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"である
$ gauge run specs
# Blog E2E
## Get Blogs ✔ ✔ ✔ ✔ ✔ ✔ ✔
すべて通りました👍
無事DBからデータを取得し、Rest層がJSONデータを返しているようです👍
明日、明後日でアドベントカレンダーも終了を迎えます。
LifeSyncのアプリケーションとしてはトップページでブログの一覧を見せることまでしか機能の作りこみはできていませんが、残りの2日間を使ってK8s環境でWeb, Bff, API, DBのすべてが起動するようにしていこうと思います👍