不労所得獲得装置開発その5 ～ yomitaku（読択）- 本の価格比較と図書館蔵書検索を統合したWebアプリ

本サイト、ほぼすべてClaude Codeで作成しました。しかもたったの数日でできてしまったのです。AI恐るべしですね。なお、以下の文章もClaude Codeに書いてもらいました。私よりも中身を理解してます。ご笑覧くださいと言いたいところですが、怖くて笑えないです💦

# yomitaku（読択）- 本の価格比較と図書館蔵書検索を統合したWebアプリを作りました

## はじめに

本好きの皆さん、気になる本を見つけた時にこんな経験はありませんか？

- 「この本、どこで買うのが一番安いかな？」
- 「図書館にあるなら借りて読みたいな」
- 「新品と中古、どっちがお得？」

そんな悩みを解決するために、**yomitaku（読択）**という書籍検索・価格比較・図書館蔵書検索サービスを作りました。

🔗 **サービスURL**: https://www.yomitaku.com

## yomitakuの特徴

### 📚 統合的な書籍情報検索

- **複数APIの統合**: OpenBD APIと楽天ブックスAPIを組み合わせて、豊富な書籍メタデータを提供
- **ISBN検索対応**: ISBN-10、ISBN-13の両形式に対応
- **高解像度カバー画像**: 美しい書籍カバー表示で視覚的に分かりやすく

### 💰 価格比較機能

- **新品価格**: Amazon、楽天、Yahoo!ショッピングの新品価格を一括比較
- **中古価格**: 楽天市場とYahoo!ショッピングの中古価格も表示
- **最安値表示**: 価格順ソートで最安値が一目で分かる
- **配送料情報**: Amazon Prime、楽天送料無料ラインなど配送料情報も表示

### 📖 図書館蔵書検索

- **全国対応**: カーリルAPIと連携して全国の図書館蔵書を検索
- **リアルタイム在庫**: 「利用可能」「貸出中」「予約中」のリアルタイム状況
- **予約リンク**: 図書館の予約システムへの直接リンク
- **設定保存**: 都道府県・市区町村の設定をブラウザに自動保存

### 📊 ジャンル別ランキング

- **10ジャンル対応**: 小説、漫画、ビジネス書など幅広いジャンル
- **トップ10表示**: 各ジャンルの売上ランキングトップ10を表示
- **視覚的なランキング**: カバー画像付きで分かりやすいランキング表示

## 技術的な特徴

### Modern Rails 8アーキテクチャ

```ruby
# Rails 8の"Solid"スタックを採用
- Solid Cache: データベース型キャッシュ
- Solid Queue: バックグラウンドジョブ処理
- SQLite3: 本番環境含むすべての環境で使用
```

### パフォーマンス最適化

**背景キャッシュウォーミング**
```ruby
class RefreshRankingCacheJob < ApplicationJob
  def perform
    # 20時間ごとにランキングデータを事前取得
    service = RakutenRankingService.new
    service.warm_cache(10)

    # 次回実行をスケジュール
    RefreshRankingCacheJob.set(wait: 20.hours).perform_later
  end
end
```

**サーキットブレーカーパターン**
```ruby
# API制限に達した場合の自動回復機能
if Rails.cache.exist?(RATE_LIMIT_CACHE_KEY)
  Rails.logger.warn "API rate limited, using stale cache"
  return return_cached_or_error("Rate limited")
end
```

### フロントエンド技術

- **Rails 8 Import Maps**: バンドラー不要のモダンJavaScript
- **Turbo + Stimulus**: プログレッシブエンハンスメント
- **レスポンシブデザイン**: モバイルファーストアプローチ
- **遅延読み込み**: 画像の遅延読み込みでページ速度向上

## 主要な実装

### 1. 複数API統合によるデータ取得

```ruby
class Book
  def self.search_by_isbn(isbn)
    # OpenBD APIからメタデータ取得
    openbd_data = fetch_from_openbd(isbn)

    # 楽天APIから価格・在庫情報取得
    rakuten_data = fetch_from_rakuten(isbn)

    # データをマージして統合的な書籍情報を作成
    merge_book_data(openbd_data, rakuten_data)
  end
end
```

### 2. インテリジェントキャッシング

```ruby
def get_genre_rankings(genres_config, limit_per_genre = 10)
  cache_key = "genre_rankings_#{limit_per_genre}_#{Date.current.strftime('%Y%m%d')}"
  cached_genres = Rails.cache.read(cache_key)

  return cached_genres if cached_genres.present?

  # API呼び出しとキャッシュ保存
  # 24時間キャッシュ + 背景更新
end
```

### 3. 図書館検索のUX最適化

```javascript
// ユーザー設定の自動復元
function loadSavedPreferences() {
  const savedPrefecture = localStorage.getItem('library-search-prefecture');
  if (savedPrefecture) {
    prefSelect.value = savedPrefecture;
    // 自動検索トリガー
    autoSearchCompleted = true;
    searchBtn.click();
  }
}
```

## 開発で工夫した点

### 1. API制限対策

楽天APIの制限に対応するため、サーキットブレーカーパターンを実装：

```ruby
# 429エラー検出時の自動バックオフ
if response.code == "429"
  backoff_until = RATE_LIMIT_BACKOFF_HOURS.hours.from_now
  Rails.cache.write(RATE_LIMIT_CACHE_KEY, true, expires_in: RATE_LIMIT_BACKOFF_HOURS.hours)
  return return_cached_or_error(cache_key, "API rate limit exceeded")
end
```

### 2. ユーザー体験の向上

- **背景データ取得**: ユーザーを待たせない非同期処理
- **設定保存**: 一度設定した都道府県・市区町村を自動保存
- **エラーハンドリング**: API障害時も適切なフォールバック

### 3. 品質保証

```bash
# 毎回のコミット前に実行
bin/rails test     # 127のテストケース
bin/rubocop        # コードスタイルチェック
bin/brakeman       # セキュリティ検査
```

## 技術スタック

| 分野 | 技術 |
|------|------|
| バックエンド | Rails 8.0.2 |
| データベース | SQLite3 (本番含む) |
| フロントエンド | Import Maps + Turbo + Stimulus |
| キャッシュ | Solid Cache |
| ジョブ処理 | Solid Queue |
| デプロイ | Kamal + Docker |
| API | OpenBD、楽天ブックス、カーリル |

## パフォーマンス指標

- **ページ読み込み**: 初回2秒以下、キャッシュ時1秒以下
- **API応答**: 背景キャッシュにより即座に表示
- **図書館検索**: 3-5秒で全国検索結果表示
- **テストカバレッジ**: 127テストケース、0エラー

## 今後の展望

- **書評機能**: ユーザーレビューシステム
- **お気に入り機能**: 読みたい本リスト
- **価格アラート**: 価格変動通知
- **API拡張**: より多くの書店との連携

## おわりに

yomitakuは「読みたい本をもっと気軽に見つけて、手に入れる」をコンセプトに作ったサービスです。

Rails 8の新機能を活用したモダンなアーキテクチャで、複数のAPIを統合し、ユーザーフレンドリーなインターフェースを実現しました。

本好きの皆さんにとって少しでも役立つサービスになれば嬉しいです。ぜひお試しください！

🔗 **yomitaku**: https://www.yomitaku.com
📁 **GitHub**: リポジトリは非公開ですが、技術的な質問があればお気軽にコメントください

## 技術的な質問・フィードバック大歓迎です！

特に以下のような点について議論できれば嬉しいです：

- Rails 8のSolidスタックの活用方法
- 複数API統合時のベストプラクティス
- SQLite3本番運用の知見
- モダンRailsアプリのパフォーマンス最適化

コメントお待ちしています！ 📚✨