コンテンツにスキップ

コード概要

ここでは、Accellaを使ってデータベースを利用したWebアプリケーションを作成する際のコードを簡単に紹介します。

テーブル定義

データベースのテーブル定義とマイグレーションにはPrismaのスキーマを使用します。 定義したテーブルの情報に従って、マイグレーションファイルを生成することができます。

db/schema/main.prisma
model User {
id Int @id @default(autoincrement())
firstName String
lastName String
age Int?
}

O/R マッピング

Accellaでは、ORMライブラリとしてActive Recordパターンで設計されたAccel Recordを使用しています。 同期的なインターフェースにより、awaitを書かなくてもよいこと、アソシエーションの暗黙的な遅延ロードができるという特徴があります。

import { User } from "src/models";
// Create a new user
const user: User = User.create({
firstName: "John",
lastName: "Doe",
});
// Update the user
user.update({
age: 26,
});
// Get all users
for (const user of User.all()) {
console.log(user.firstName);
}
// Find a user
const john: User | undefined = User.findBy({
firstName: "John",
lastName: "Doe",
});
// Delete the user
john?.delete();

モデルクラスの拡張

モデルに対応したクラスを拡張することで、バリデーション、コールバック、独自のメソッドなどを定義することができます。

src/models/user.ts
import { before } from "accel-record";
import { validates } from "accel-record/validations";
import { ApplicationRecord } from "./applicationRecord.js";
export class UserModel extends ApplicationRecord {
// モデルのバリデーションを定義
static validations = validates(this, [
["firstName", { presence: true }],
["lastName", { presence: true }],
]);
@before("save")
myCallback() {
// このメソッドは保存前に呼び出されます
}
// フルネームを取得するメソッドを定義
get fullName(): string {
return `${this.firstName} ${this.lastName}`;
}
}

ページの用意

ファイルベースのルーティングになり、基本的にはルーティング用の記述は不要です。 AstroコンポーネントはReactコンポーネントやVueのSFCのように、JavaScriptでの処理とDOM構造を1つのファイルで記述します。これにより、型安全なテンプレートレンダリングが実現できます。

src/pages/users/index.astro
---
import { paginate } from "accel-web";
import { User } from "src/models";
import Layout from "../layouts/Layout.astro";
const page = Number(Astro.locals.params.p) || 1;
const pager = paginate(User.order('id', 'desc'), {
page,
per: 10,
window: 2,
});
const { Nav, PageEntriesInfo } = pager;
---
<Layout>
<h2>User List</h2>
<table>
<thead>
<tr>
<th>ID</th>
<th>Email</th>
</tr>
</thead>
<tbody>
{
pager.records.map((user) => (
<tr>
<td>{user.id}</td>
<td>{user.email}</td>
</tr>
))
}
</tbody>
</table>
<!-- Pagination -->
<div><Nav /></div>
<div><PageEntriesInfo /></div>
</Layout>

テスト

プロジェクト開始後すぐにテストを構築できるように、Vitestがセットアップされています。また、Accel Record用のファクトリーも用意されており、簡単にテスト用のデータを作成することができます。

tests/user.test.ts
import { User } from "src/models";
import { $User } from "./factories/user";
test("create a user", () => {
const user = $User.create({
firstName: "John",
lastName: "Doe",
});
expect(user.fullName).toBe("John Doe");
expect(User.count()).toBe(1);
});