SQLiteでデータを永続化する
ユーザー同士がやり取りするコメントは、どこかに保存する必要があります。もし保存しないと、サーバーを再起動した際に全てのコメントが消えてしまいます。
今回のアプリケーションでは、SQLiteを用いてコメントデータを永続化しています。それでは、具体的な実装を見ていきましょう。
テーブルを作成する
データベースをセットアップする処理は、database.jsにまとめています。SQLiteのテーブルを作成する部分を見てみましょう。いくつかのテーブルがありますが、ここでは代表してcommentsテーブルの定義を紹介します。
// commentsテーブル CREATE TABLE IF NOT EXISTS comments ( id TEXT PRIMARY KEY, userId TEXT NOT NULL, postTime TEXT NOT NULL, updateTime TEXT NOT NULL, parentCommentId TEXT, content TEXT NOT NULL, FOREIGN KEY (userId) REFERENCES users(id) );
主キーはidで、各コメントを一意に識別します。userIdはコメントを投稿したユーザーのID、postTimeとupdateTimeはそれぞれ投稿時間と更新時間を表します。parentCommentIdは返信先のコメントID、contentはコメントの内容です。
userIdには外部キー制約を設けており、usersテーブルのIDと紐づけています。これにより、存在しないユーザーがコメントを投稿することを防ぎます。この他に、usersテーブルとreactionsテーブルも定義しています。それぞれの役割は以下のとおりです。
| テーブル名 | 主なカラム | 役割 |
|---|---|---|
| users | id, name, avatar | コメント投稿者情報 |
| comments | id, userId, content, postTime | 各コメント本文と投稿時刻 |
| reactions | userId, commentId, reactionChar | 絵文字リアクション(👍, 🔥 など) |
データの保存と取得
コメントの保存は、前述のhandleCommentPost()関数で行っています。INSERT文を使って新しいコメントをcommentsテーブルに追加しています。
該当する部分を再掲しましょう。
const stmt = db.prepare( "INSERT INTO comments (id, userId, postTime, updateTime, parentCommentId, content) VALUES (?, ?, ?, ?, ?, ?)", ); stmt.run([ msg.comment.id, msg.comment.userId, msg.comment.postTime, msg.comment.updateTime, msg.comment.parentCommentId, msg.comment.content, ]);
このコードでは、db.prepare()でINSERT文を準備し、stmt.run()で実際にデータを挿入しています。パラメータにはコメントの各フィールドを渡しています。?はプレースホルダで、SQLインジェクションを防ぐために使用しています。これにより、ユーザーからの入力が直接SQL文に組み込まれることを防ぎ、安全にデータを保存できます。
更新や削除についても、同様にSQL文を用いて実装しています。SQL文の書き方に慣れていれば、とても簡単に実装できると思います。
まとめ
本記事を通して、InputManJSのコメントコンポーネント(GcComment)とSocket.IOを組み合わせて、リアルタイムチャットアプリケーションを構築する方法を解説しました。また、SQLiteを用いたデータの永続化についても触れました。
このアプローチを取ることで、ユーザーが投稿・更新・削除したコメントを、他のユーザーにも即座に反映される体験を提供できます。もし、さらに実用度の高いアプリケーションを目指す場合は、ルーム機能や認証機能の追加を検討すると良いでしょう。
本記事では分量の都合で触れられませんでしたが、リアクション機能についてもコメント機能と同様の仕組みで実装しています。ぜひサンプルコードを参照してみてください。

