Sinatraで作る中高生向け悩み相談Webサービス「Ballon」- 設計と基本実装 (Part 1)

この記事は、Sinatraを使用した中高生向け悩み相談Webサービス「Ballon」の開発過程を詳細に解説するシリーズの第1部です。

- Part 1 (本編): アプリケーションの概要、技術選定の理由、基本設計
- Part 2: ユーザー認証システムの実装と詳細な解説
- Part 3: 悩み投稿機能の実装とデータベース設計の詳細
- Part 4: 回答機能と「いいね」機能の実装、セキュリティ対策
- Part 5: パフォーマンス最適化、テスト戦略、デプロイメント手法

## はじめに

こんにちは！今回は、Rubyのマイクロフレームワークである**Sinatra**を使用して、中高生向けの悩み相談Webサービス「Ballon」を作成した過程を共有します。このWebサービスは、高校2年生の秋から3年生にかけて開発しました。

Ballonは、悩みの共有とコミュニティサポートを組み合わせることで、若者の精神的健康とピアサポートを促進することを目的としています。本記事では、アプリケーションの設計思想から基本的な実装まで、詳細に解説していきます。

## 技術スタックと選定理由

まず、このプロジェクトで使用した主要な技術とその選定理由を説明します。

1. **Ruby**: 
   - 選定理由：Rubyは読みやすく書きやすい言語で、高い生産性を実現します。また、豊富なライブラリ（gem）のエコシステムがあり、開発を効率化できます。高校生でも比較的短期間で習得しやすい言語でもあります。

2. **Sinatra**:
   - 選定理由：Sinatraは軽量で柔軟性が高いマイクロフレームワークです。Railsと比較して学習曲線が緩やかで、小規模なアプリケーションに適しています。また、必要最小限の機能を提供しつつ、カスタマイズの自由度が高いため、高校生の学習にも適しています。

3. **ActiveRecord**:
   - 選定理由：ActiveRecordはRuby on Railsで使用されるORMですが、Sinatraでも使用可能です。データベース操作を簡潔に記述でき、SQLの知識が浅い高校生でもデータベースを扱えるようになります。

4. **SQLite3**:
   - 選定理由：開発環境では軽量で設定が簡単なSQLite3を選択しました。小規模なアプリケーションの開発には十分な機能を提供し、高校生が個人のPCで簡単に開発環境を構築できます。

## アプリケーションの構造

Ballonは以下の主要な機能を持っています：

1. ユーザー認証（サインアップ、サインイン、サインアウト）
2. 悩みの投稿と表示
3. 悩みへの回答機能
4. 回答への「いいね」機能
5. ユーザープロフィール

これらの機能を実現するために、MVCアーキテクチャを採用しています。Sinatraは明示的なMVCの構造を強制しませんが、コードの整理と保守性のために、以下のような構造を採用しました：

```
project_root/
│
├── app.rb          # メインのアプリケーションファイル
├── models.rb       # モデル定義
├── views/          # ビューテンプレート
│   ├── layout.erb
│   ├── index.erb
│   └── ...
├── public/         # 静的ファイル
│   ├── css/
│   └── js/
└── db/             # データベース関連
    └── migrations/ # マイグレーションファイル
```

## データベース設計

アプリケーションは以下のテーブルを使用しています：

1. `users`: ユーザー情報を管理
2. `worries`: 悩み投稿を管理
3. `answers`: 悩みへの回答を管理
4. `likes`: 回答への「いいね」を管理

これらのテーブル間の関係は以下の通りです：

- ユーザーは複数の悩みを持つ（1対多）
- 悩みは複数の回答を持つ（1対多）
- ユーザーは複数の回答を持つ（1対多）
- ユーザーは複数の「いいね」を行える（1対多）
- 回答は複数の「いいね」を持つ（1対多）

この設計により、ユーザー、悩み、回答、「いいね」の関係を適切に表現し、効率的なデータ取得が可能になります。

## 基本的なアプリケーション設定

アプリケーションの基本設定を`app.rb`ファイルで行います。以下に、その核となる部分を示します：

```ruby:app.rb
require 'bundler/setup'
Bundler.require
require 'sinatra/reloader' if development?
require './models'

enable :sessions

helpers do
  def current_user
    User.find_by(id: session[:user])
  end
end

before '/worries' do
  if current_user.nil?
    redirect '/'
  end
end

# 以下、各ルーティングの定義
```

このコードの各部分について説明します：

1. `require 'bundler/setup'`と`Bundler.require`: これにより、Gemfileにリストされたすべてのgemをロードします。

2. `require 'sinatra/reloader' if development?`: 開発環境でのみ、コードの変更を自動的に反映するreloaderを有効にします。

3. `require './models'`: モデルの定義を含むファイルをロードします。

4. `enable :sessions`: セッションを有効にし、ユーザー認証を可能にします。

5. `helpers`ブロック: ビューで使用するヘルパーメソッドを定義します。ここでは`current_user`メソッドを定義し、現在ログインしているユーザーを取得できるようにしています。

6. `before '/worries'`ブロック: `/worries`で始まるすべてのルートに対して、ユーザーがログインしていることを確認します。ログインしていない場合は、トップページにリダイレクトします。

この基本設定により、セッション管理、ユーザー認証、開発環境でのホットリロードなどの機能が有効になります。

## セキュリティとプライバシーへの配慮

中高生を対象とするサービスであるため、セキュリティとプライバシーには特に注意を払う必要があります：

1. 強固なパスワードポリシーの実装
2. センシティブな情報の暗号化
3. 不適切なコンテンツのフィルタリング
4. ユーザーの年齢確認メカニズム
5. 保護者の同意を得るプロセスの実装

これらの詳細な実装については、後続のパートで解説します。

## まとめと次回予告

Part 1では、中高生向け悩み相談Webサービス「Ballon」の概要、技術選定の理由、基本的な設計について説明しました。Sinatraを選んだ理由や、データベース設計の考え方など、アプリケーション開発の基礎となる部分を詳しく解説しました。

次回のPart 2では、ユーザー認証システムの実装に焦点を当てます。`has_secure_password`の使用方法や、セッション管理の詳細、セキュリティ上の考慮事項などを解説する予定です。

引き続き、このシリーズでは実装の詳細や、直面した課題とその解決策、さらにはパフォーマンス最適化やテスト戦略についても触れていきます。

ご質問やフィードバックがありましたら、コメント欄にてお待ちしています！

## 参考リンク

- [Sinatra公式ドキュメント](http://sinatrarb.com/)
- [ActiveRecord公式ドキュメント](https://guides.rubyonrails.org/active_record_basics.html)
- [Ruby公式サイト](https://www.ruby-lang.org/)