[Rust] tokioのORM「toasty」を今のうちに少しだけ

tokioの非同期ORMの「toasty」に今のうちに少しだけ触れておく
以下postが日本語でわかりやすく書かれているので参考になるかと

触ってみる
現在時(2024/12/20)、まだcrates.ioには公開されていないようなので直接リポジトリの中身を覗いてみる。とりあえずcloneする。
$ git clone https://github.com/tokio-rs/toasty.git
現在時点での最新のコミットはce4e4a6fe25cb3b2c400331ed125d4a82ed960ff

examples
ディレクトリ内にサンプルがいくつか入っている。各サンプルに存在するschema.toasty
ファイルがPrismaでいうところのschema.prisma
ファイルに相当すると思われる。
toasty/examples
├── composite-key
│ ├── Cargo.toml
│ ├── schema.toasty ← これ
│ └── src
│ ├── db
│ │ ├── ...
│ └── main.rs
├── cratehub
│ ├── Cargo.toml
│ ├── schema.toasty ← これ
│ └── ...
├── hello-toasty
│ ├── ...
└── ...

hello-toasty
のTodo
モデルに少し変更を加えてみる。examples/hello-toasty/schema.toasty
のTodo
にStringのcontent
とOption<String>のremarks
を追加する。
model Todo {
...
content: String,
remarks: Option<String>,
}

コード生成コマンドを実行
$ cargo run -p toasty-cli -- gen --schema "examples/hello-toasty/schema.toasty" "examples/hello-toasty/src/db"
examples/hello-toasty/src/db
ディレクトリ内の関連ファイルが更新され、content
フィールドとremarks
フィールドの情報や関連メソッドが追加されていることが確認できる。
pub struct Todo {
...
pub content: String,
pub remarks: Option<String>,
}
...
pub fn content(mut self, content: impl Into<String>) -> Self {
self.stmt.set_value(4, content.into());
self
}
pub fn remarks(mut self, remarks: impl Into<String>) -> Self {
self.stmt.set_value(5, remarks.into());
self
}

examples/hello-toasty/src/main.rs
のTodo
を挿入する箇所にて、content
, remarks
の値をセットしてみる。
// 77行目〜
let todo = u2
.todos()
.create()
.title("finish toasty")
.content("as always") // 追加
.remarks("by today") // 追加
.exec(&db)
.await
.unwrap();
...
// 113行目〜
let mut user = User::create()
.name("Ann Chovey")
.email("ann.chovey@example.com")
.todo(
Todo::create()
.title("Make pizza")
.content("in the mood for Margherita pizza"), // 追加
)
.todo(
Todo::create()
.title("Sleep")
.content("Up early tomorrow.") // 追加
.remarks("By 11 p.m. on December 20, 2024."), // 追加
)
.exec(&db)
.await
.unwrap();
user.update()
.todo(
Todo::create()
.title("might delete later")
.content("without forgetting"), // 追加
)
.exec(&db)
.await
.unwrap();
// 登録内容確認用に上の処理に続けて以下の一連を追加
let mut todos = user.todos().all(&db).await.unwrap();
while let Some(todo) = todos.next().await {
let todo = todo.unwrap();
println!("TODO = {todo:#?}");
}

hello-toasty
を実行してみる。
$ cargo run -p example-hello-toasty
↓ 結果
...
TODO = Todo {
...
content: "as always",
remarks: Some(
"by today",
),
}
...
TODO = Todo {
...
title: "Make pizza",
content: "in the mood for Margherita pizza",
remarks: None,
}
TODO = Todo {
...
content: "Up early tomorrow.",
remarks: Some(
"By 11 p.m. on December 20, 2024.",
),
}
TODO = Todo {
...
title: "might delete later",
content: "without forgetting",
remarks: None,
}
追加したcontent
, remarks
の値が登録および取得できていることが確認できた。

所感
Prismaっぽい。
各フィールドの値をsetter的メソッドによって個別にセットするやり方は、項目のセットし忘れをコンパイル段階で弾けない等々ありそう...
(項目追加対応時、コンパイルエラーが起きてる箇所だけなおせば対応完了!みたいなのもやりづらい)
まだこれから洗練されていくと思われるので注目しておきたい。