メインコンテンツにスキップ

Tabnine

Tabnine は、IDE (例: VS Code、WebStorm、IntelliJ、...) の拡張機能として提供される AI ソフトウェア開発プラットフォームです。

概要

開発者がより速くコードを書けるように支援します。

  • 小さな反復的なコーディングタスクに対して、エディタ内でコンテキストを認識したコード補完候補を提供することで
  • より高度なタスクと詳細な指示のために、統合されたチャットを提供することで

Prisma ORM を Tabnine と併用する理由

Tabnine のような AI エディタは、開発者の生産性を大幅に向上させる強力なツールです。特に以下のワークフローで効果を発揮します。

  • データモデリングとデータベーススキーマ設計
  • データベースクエリの構築と最適化
  • CRUD 機能およびその他のボイラープレートコードの生成
  • TypedSQL で使用できるプレーンな SQL クエリの生成
  • ユニットテストと統合テスト用のコード生成
  • 大規模なリファクタリングのガイド
  • シーディングスクリプトの生成

Prisma スキーマの活用

Prisma は独自のスキーマを持っているため、Tabnine はデータの基本的な形状を理解し、スタックの他の部分のコードを書くのに役立ちます。

したがって、まず Prisma スキーマを定義し、次に Tabnine を使用してその周りにアプリケーション層 (API 呼び出し、DTO、ビジネスロジック、サードパーティ統合などを含む) を構築することをお勧めします。

データモデリングとデータベーススキーマ設計

Tabnine はどのように役立つか

データベーススキーマをゼロから設計するには、多くのボイラープレートが必要で、時間がかかる場合があります。

Tabnine は、次の方法でこのプロセスを加速できます。

  • モデル、インデックス、制約、およびリレーションシップのボイラープレートを生成します。
  • 命名規則やその他の規則に従うことで、スキーマの一貫性を維持します。
  • 一般的なデータベースパターンに基づいて、モデルとフィールドの定義を自動補完します。
  • 命名規則に基づいて、リレーションシップとフィールドタイプを提案します。

例: Prisma スキーマの定義

プロンプト

ユーザー、組織、およびサブスクリプションモデルを持つ SaaS アプリケーションの Prisma スキーマを定義します。リレーションシップが適切に設定されていることを確認してください。

生成されたコード

generator client {
provider = "prisma-client-js"
}

datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}

model User {
id Int @id @default(autoincrement())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
email String @unique
name String
organization Organization @relation(fields: [organizationId], references: [id])
organizationId Int
}

model Organization {
id Int @id @default(autoincrement())
name String
slug String @unique
subscription Subscription?
users User[]
}

model Subscription {
id Int @id @default(autoincrement())
organization Organization @relation(fields: [organizationId], references: [id])
organizationId Int @unique
plan String
status Status
}

enum Status {
Active
Paused
Expired
}

データベースクエリの構築と最適化

Tabnine はどのように役立つか

Prisma ORM は、データベースクエリを直感的に記述するための便利な高レベル API を提供します。ただし、フィルター、ページネーション、および高度なパターンを含むクエリは、依然として構築が複雑になる可能性があります。

Tabnine は、次の方法で役立ちます。

  • スキーマに基づいて Prisma クエリを自動補完します。
  • フィルター用の where 句と、ページネーションロジック用の skip / take オプションを提案します。
  • 効率とパフォーマンスの最適化を支援します。

例: リレーションシップを使用したデータのフェッチ

プロンプト

アクティブなサブスクリプションを持つ組織からすべてのアクティブなユーザーをフェッチする Prisma クエリを生成します。クエリ結果にユーザーの組織に関するデータを含めます。

生成されたコード

const activeUsers = await prisma.user.findMany({
where: {
organization: {
subscription: {
status: "ACTIVE"
}
}
},
include: {
organization: true
}
});

CRUD 機能およびその他のボイラープレートコードの生成

Tabnine はどのように役立つか

ほとんどのアプリケーションでは、データベーススキーマの構造から通常派生する基本的な CRUD 操作またはその他のボイラープレートコードが必要です。たとえば、API レイヤーは、特定のモデルのレコードを作成、読み取り、更新、または削除できる一連の HTTP エンドポイントを公開する場合があります。同様に、フロントエンドは、これらの API エンドポイントと対話し、それに応じて UI を更新するためのデータフェッチングと状態管理ロジックを備えています。

このコードを手動で記述する代わりに、Tabnine は次の方法でこのプロセスを高速化できます。

  • バックエンド用の Prisma createreadupdate、および delete 操作、およびフロントエンド用の UI コンポーネントを生成します。
  • 関数名と引数タイプを自動補完します。
  • DTO、エラー処理、一貫性のある API 設計などのベストプラクティスに従いながら、ボイラープレートコードを記述します。

例: Next.js での CRUD 機能の生成

プロンプト

上記のスキーマのユーザーモデルに基づいて、Next.js アプリの CRUD 機能を生成します。

生成されたコード

API エンドポイント
filename=app/api/users/routes.ts
import { NextResponse } from 'next/server';
import prisma from '../../../lib/prisma';

export async function GET() {
const users = await prisma.user.findMany({
include: { organization: true },
});
return NextResponse.json(users);
}

export async function POST(request: Request) {
const body = await request.json();
const user = await prisma.user.create({
data: {
email: body.email,
name: body.name,
organization: {
connect: { id: body.organizationId },
},
},
include: { organization: true },
});
return NextResponse.json(user);
}

export async function PUT(request: Request) {
const body = await request.json();
const user = await prisma.user.update({
where: { id: body.id },
data: {
email: body.email,
name: body.name,
organizationId: body.organizationId,
},
include: { organization: true },
});
return NextResponse.json(user);
}

export async function DELETE(request: Request) {
const { searchParams } = new URL(request.url);
const id = searchParams.get('id');
const user = await prisma.user.delete({
where: { id: Number(id) },
});
return NextResponse.json(user);
}
React コンポーネント
filename=app/components/User.tsx
import React, { useState, useEffect } from 'react';

interface User {
id: number;
email: string;
name: string;
organizationId: number;
}

const User: React.FC = () => {
const [users, setUsers] = useState<User[]>([]);
const [newUser, setNewUser] = useState({ email: '', name: '', organizationId: 0 });

useEffect(() => {
fetchUsers();
}, []);

const fetchUsers = async () => {
const response = await fetch('/api/users');
const data = await response.json();
setUsers(data);
};

const createUser = async () => {
await fetch('/api/users', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(newUser),
});
fetchUsers();
setNewUser({ email: '', name: '', organizationId: 0 });
};

const deleteUser = async (id: number) => {
await fetch(`/api/users?id=${id}`, { method: 'DELETE' });
fetchUsers();
};

return (
<div>
<h2>Users</h2>
<ul>
{users.map((user) => (
<li key={user.id}>
{user.name} ({user.email}) - Org ID: {user.organizationId}
<button onClick={() => deleteUser(user.id)}>Delete</button>
</li>
))}
</ul>
<h3>Create New User</h3>
<input
type="text"
placeholder="Name"
value={newUser.name}
onChange={(e) => setNewUser({ ...newUser, name: e.target.value })}
/>
<input
type="email"
placeholder="Email"
value={newUser.email}
onChange={(e) => setNewUser({ ...newUser, email: e.target.value })}
/>
<input
type="number"
placeholder="Organization ID"
value={newUser.organizationId}
onChange={(e) => setNewUser({ ...newUser, organizationId: Number(e.target.value) })}
/>
<button onClick={createUser}>Create User</button>
</div>
);
};

export default User;

TypedSQL で使用するためのプレーンな SQL クエリの生成

Tabnine はどのように役立つか

Prisma はクエリ用の高レベル API を提供していますが、クエリのよりローレベルの制御が必要になる場合があります。このような場合、TypedSQL を使用できます。これは、Prisma ORM の raq SQL クエリに完全な型安全性を提供します。

一般的なユースケースの 1 つは、上記のスキーマ例のさまざまなサブスクリプションステータスのパーセンテージを計算するなどの集計クエリです。

Tabnine は、次の方法で支援できます。

  • Prisma スキーマに基づいて SQL クエリを生成します。
  • 手動による試行錯誤なしに複雑な集計を構造化します。
  • クエリをアプリケーションコードに統合します。

例: アクティブ、期限切れ、および一時停止中のサブスクリプションのパーセンテージの計算

プロンプト

アクティブ、一時停止、および期限切れのサブスクリプションのパーセンテージを返す SQL クエリを生成します。

生成された SQL クエリ

prisma/sql/subscriptionsReport.sql
SELECT 
status,
COUNT(*) * 100.0 / (SELECT COUNT(*) FROM "Subscription") AS percentage
FROM "Subscription"
GROUP BY status;

アプリケーションコード

import { PrismaClient } from '@prisma/client'
import { subscriptionsReport } from '@prisma/client/sql'

const prisma = new PrismaClient();

const usersWithPostCounts = await prisma.$queryRawTyped(subscriptionsReport())
console.log(usersWithPostCounts)

ユニットテストと統合テスト用のコード生成

Tabnine はどのように役立つか

テストを記述することで、Prisma ベースのアプリケーションが正しく機能し、要件と期待どおりに動作することが保証されます。ただし、テストの記述は時間がかかるアクティビティであり、多くの場合、予測可能で反復的なパターンに従います。

Tabnine は、次の方法でテストの記述を大幅に高速化できます。

  • ユニットテストと統合テストの両方のテストボイラープレートを生成します。
  • Prisma データベースインタラクションのモックとフィクスチャを提案します。
  • ベストプラクティスに従うようにテストケースを構造化するのを支援します。
  • Prisma を実際のデータベースまたはインメモリデータベースでテストするための統合テストスキャフォールディングを提供します。

例: Prisma サービス用のユニットテストの記述

プロンプト

すべてのアクティブなユーザーをフェッチする Prisma サービス関数の Jest ユニットテストを生成します。

生成されたコード

filename=__tests__/userService.test.ts
import { prismaMock } from '../prisma/singleton';
import { getActiveUsers } from '../services/userService';

test('should return only active users', async () => {
prismaMock.user.findMany.mockResolvedValue([
{ id: 1, name: 'Alice', email: 'alice@example.com' },
{ id: 2, name: 'Bob', email: 'bob@example.com' }
]);

const users = await getActiveUsers();
expect(users).toHaveLength(2);
expect(users[0].email).toBe('alice@example.com');
});

大規模なリファクタリングのガイド

Tabnine はどのように役立つか

Prisma ORM の型安全なクエリのおかげで、リファクタリングは他の ORM よりも安全で予測可能です。スキーマを変更すると、生成された Prisma Client コードが更新され、TypeScript コンパイラが変更が必要なすべての場所を強調表示します。

ただし、ビジネスロジックや複雑なクエリを調整する必要がある場合など、リファクタリング中にさらに困難な状況が発生する可能性があります。

Tabnine は、リファクタリング中に次の方法で支援できます。

  • コード内のパターンを識別し、一貫性を維持しながらリファクタリングを提案します。
  • スキーマ変更後のデータベースクエリの更新を支援し、手動の労力を削減します。
  • ロジックを簡素化および最適化するための関数書き換えを提供します。
  • コードベース全体で処理する必要がある破壊的な変更を提案します。

例: スキーマ変更後の Prisma クエリのリファクタリング

プロンプト

この Prisma クエリをリファクタリングして、ユーザーモデルの deletedAt タイムスタンプフィールドを使用したソフト削除をサポートします。

初期コード

const users = await prisma.user.findMany();

リファクタリングされたコード

const users = await prisma.user.findMany({
where: { deletedAt: null }
});

シーディングスクリプトの生成

Tabnine はどのように役立つか

データベースに現実的なテストデータをシードするのは面倒な場合があります。現実的なシードデータは、開発中に役立ちます。なぜなら、実世界で使用した場合のアプリケーションのより良い印象を開発者に与えるからです。Tabnine は、次の方法でデータベースシードを支援できます。

  • スキーマと特定の要件に基づいて、構造化されたシードデータを含むスクリプトを生成します。
  • アプリをテストするために使用できるリアルなプレースホルダーデータを作成します。
  • エッジケースをカバーするために特定のデータを生成します。

例: シードスクリプトの作成

プロンプト

ユーザー、組織、およびサブスクリプションモデルをポピュレートするための Prisma シードスクリプトを生成します。

生成されたコード

import { PrismaClient } from "@prisma/client";

const prisma = new PrismaClient();

async function main() {
await prisma.organization.create({
data: {
name: "Prisma Corp",
slug: "prisma-corp",
subscription: {
create: {
plan: "PRO",
status: "ACTIVE"
}
},
users: {
create: [
{ name: "Alice Doe", email: "alice@prisma.io" },
{ name: "Bob Smith", email: "bob@prisma.io" }
]
}
}
});

console.log("Seed data created successfully");
}

main()
.catch((e) => {
console.error(e);
process.exit(1);
})
.finally(async () => {
await prisma.$disconnect();
});

Prisma とのつながりを維持する

以下とつながることで、Prisma の旅を続けましょう。 活発なコミュニティ。最新情報を入手し、参加し、他の開発者と協力しましょう

皆様のご参加を心から歓迎し、コミュニティの一員としてお迎えできることを楽しみにしています!