作りたい機能
ユーザーが注文後にその注文の口コミを一度投稿すると、二回目以降は投稿できないようにする。
最初に思いついた解決方法
口コミ情報テーブルのorder_idと注文履歴テーブルのorder_idを付け合せて、一致するものを「投稿済み」に変更する方法。
手順
- 親コンポーネントでそれぞれの情報をフェッチして、子コンポーネントに渡す。
- 子コンポーネントにてincludeで付け合せて、表示を切り替える。
page.tsx
export default async function OrdersPage() {
const orders = await fetchOrders();
const reviews_id = await fetchIsReviewed();
return (
<>
<div className="space-y-6">
{orders.length > 0 ? (
orders.map((order) => (
<OrderCard key={order.id} order={order} reviews_id={reviews_id} />
))
) : (
<div>過去の注文がありません。</div>
)}
</div>
</>
);
}
ordercard.ts
export default function OrderCard({ order, reviews_id }: OrderCardProps) {
const isReviewed = reviews_id.includes(order.id);
return (
<>
{isReviewed ? (
//レビュー済みの場合
<Button variant="outline" disabled className="w-40">
投稿済み
</Button>
) : (
//未レビューの場合
<Dialog>
<DialogTrigger asChild>
<Button variant="outline" className="w-40">
口コミを書く
</Button>
</DialogTrigger>
<ReviewModal order={order} />
</Dialog>
)}
</>
);
}
特徴
-
メリット
-
データの正確性: fetchIsReviewedはreviewsテーブルから最新の情報を取得するため、データの正確性は保たれる。
-
-
デメリット
-
クエリのオーバーヘッド: 2つの独立したデータベースクエリを実行する必要がある。特にreviewsテーブルのデータ量が増加すると、fetchIsReviewedのパフォーマンスが低下する可能性がある。 -
照合ロジックが必要: アプリケーション側で2つのデータを取得し、Setやincludeなどを使って照合するロジックが必要になってしまう。
-
よりよい解決方法
注文履歴テーブルにis_reeviewed列を設けてUPDATEする方法。この方法は、ページ表示時に必要なデータベースクエリが1回で済むため、レイテンシが少なく、ユーザー体験が向上すると考えた。
手順
-
注文履歴テーブルにisReviewed列を追加: is_reviewed BOOLEAN DEFAULT FALSEという列を追加する。 -
トリガー関数の作成: 口コミテーブルにINSERTがあった場合に、注文履歴テーブルの該当行のis_reviewedをTRUEに設定するトリガー関数を作成する。 -
ポリシーの作成:注文履歴テーブルにUPDATEを許可するポリシーを作成する -
OrdersPageの修正: fetchIsReviewed関数を削除し、fetchOrders関数内で注文履歴テーブルのis_reviewed列を直接取得するように修正する。
.sql
CREATE OR REPLACE FUNCTION public.update_order_is_reviewed()
RETURNS TRIGGER AS $$
BEGIN
UPDATE public.orders
SET is_reviewed = TRUE
WHERE id = NEW.order_id;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER update_order_on_review
AFTER INSERT ON public.reviews
FOR EACH ROW
EXECUTE FUNCTION public.update_order_is_reviewed();
考察
- 一つのアクションをした後に、表示を永続的に切り替えたいという目的がある時はデータベーストリガーを選択肢に入れる。
- 一つのコンポーネントにフェッチ処理を複数記述する時は各フェッチの性質を比較して、効率的に情報取得できないかを考える。
- クライアント側で不正に表示を切り替えられる恐れがある。そのため、サーバー側でも一度口コミが投稿された注文履歴には、それ以降投稿できないような処理書いておく必要がある。

