Skip to content

Conversation

yasulab
Copy link
Member

@yasulab yasulab commented Aug 5, 2025

Fix #1373

概要

Issue #1373 を解決するための PR です。

問題

  • 現在の is_active: false では いつ非アクティブになったのか? という情報が欠けてしまう
  • 結果として、統計情報にある 道場数の推移 グラフの一部がやや不明瞭なデータになったり、xx年度の時点では、どの地域に oo の Active な Dojo があった という過去の任意の時点でのデータを参照/検証できない

解決策

  • is_active ブール値を inactivated_at タイムスタンプに置き換えることで、過去の活動履歴を保持しながら統計を正確に表示できるようにする。
  • いつ非アクティブになったのか? という情報は、幸いにも、YAML ファイルに is_active がセットされた情報から git blame でサルベージが可能
  • サルベージの実装例: https://github.com/remote-jp/remote-in-japan/blob/main/doc/upsert_data_by_readme.rb#L28-L44
readme.each.with_index(1) do |line, index|
  ...
  # Fetch latest commit info
  latest_commit_id  = `git blame #{readme_path} -L #{index},+1 --porcelain --ignore-revs-file=docs/ignore_revs.txt`.strip.lines[0].split.first
  latest_commit_at  = git.gcommit(latest_commit_id).author_date.strftime('%Y-%m-%d %H:%M:%S %z')
  latest_commit_day = git.gcommit(latest_commit_id).author_date.strftime('%Y-%m-%d')
  latest_commit_url = 'https://github.com/remote-jp/remote-in-japan/commit/' + latest_commit_id
  ...

これにより、例えば「2018年時点で関東地方に存在していたDojo一覧」のような過去の任意時点でのデータを正確に取得できるようになります。 🗾📊✨

📍 現在の実装状況

✅ Phase 1: 基盤整備(完了)

  • データベースマイグレーション(inactivated_at カラム追加、note カラムの型変更)
  • Dojoモデルの更新(active_at スコープ、reactivate! メソッドなど)
  • 基本的なテストの追加
  • 既存機能への影響なし(追加型の実装)

✅ Phase 2: YAMLサポートと統計ロジック(完了)

  • dojos:update_db_by_yaml タスクへの inactivated_at サポート追加(1行追加で実装)
  • Git履歴から inactivated_at を抽出してYAMLに反映するRakeタスク実装
    • 2フェーズ処理で行番号ずれのバグを修正
    • 冪等性を保証(再実行しても変更なし)
  • 全124個の非アクティブDojoに inactivated_at を追加完了

✅ Phase 3: データ移行とテスト(完了)

  • Git履歴から自動抽出を実行
  • 124個のDojoに inactivated_at を追加(すべて単純な履歴)
  • 統計精度が平均24.7%改善見込み
  • 包括的なテストを追加:
    • 全ての非アクティブDojoが inactivated_at を持つことを確認
    • 日付の妥当性検証(未来日付でない、created_at以降など)
    • inactivated_at を持つDojoが必ず is_active カラムを持つことを確認

✅ Phase 4: 統計ロジック更新(完了)

  • annual_dojos_with_historical_dataメソッドで過去の活動履歴を正確に集計
  • 統計精度が大幅改善(例:2018年 98→172道場)
  • 全133個のテストが通過
  • 実装の冪等性を検証済み

✅ Phase 5: 統計グラフの改善(完了)

  • 道場数グラフの「増加数」ラベルの問題を修正
    • 問題:差分計算により負の値が表示されていた
    • 解決:新規開設数を正しく計算する annual_new_dojos_count メソッドを追加
    • ラベルを「増加数」から「開設数」に変更(より意味が明確に)
    • 英語版は「Change」→「New」に変更
  • テスト環境の改善
    • テストデータを2012-2024年の全期間に拡張
    • より現実的なデータパターンを使用(COVID影響も再現)
    • 環境独立性を確保(テストDBのみを使用)

⚠️ 重要な発見

db/dojos.yaml がマスターデータであるため:

  • DBへの直接変更では不十分(次回の update_db_by_yaml で上書きされる)
  • 永続化にはYAMLファイルの更新が必須
  • データフロー: YAML → rails dojos:update_db_by_yaml → DB

📊 実装効果

  • 統計精度の大幅改善
    • 2018年: 98 → 172道場(+75.5%)
    • 2019年: 126 → 200道場(+58.7%)
    • 2020年: 148 → 222道場(+50.0%)
  • グラフ表示の改善
    • 「開設数」が常に0以上の値を表示(論理的に正しい)
    • 過去の道場数推移をより正確に反映

Action List

  • 実装計画ドキュメントを追加 34b5ab7 92f35c9 d16ae98
  • 実装前の統計データ記録 fdd31df
  • inactivated_at カラムと基本機能の実装 3c24c7b
    • データベースマイグレーション(inactivated_at カラム追加)
    • note カラムの型変更(string → text)
    • モデルメソッドとスコープの追加(active_at, reactivate! など)
    • 基本的なテストの追加
  • YAMLマスターデータを考慮した計画更新 92f35c9
  • dojos:update_db_by_yaml タスクへの inactivated_at サポート追加 11c3d41
  • Git履歴から inactivated_at を抽出してYAMLに反映するRakeタスク実装 03997a9 047db74 2832230
  • 全124個の非アクティブDojoへのデータ移行 5a548c7
  • YAMLデータ整合性のテスト追加 884afec 38ff377
  • 統計ロジックの更新(active_at スコープを使用) 521cce6
  • 道場数グラフの「開設数」表示修正 646d318 2505fcf 54e4bdd 0c95b47
  • 動作確認とベースラインとの比較 - 統計精度が大幅改善

やらないこと

🧪 テスト方法

# モデルテストの実行
bundle exec rspec spec/models/dojo_spec.rb -e "inactivated_at"
bundle exec rspec spec/models/stat_spec.rb

# 統計の変化確認(実装後)
rails runner "
  (2012..2024).each do |year|
    date = Time.zone.local(year).end_of_year
    count = Dojo.active_at(date).sum(:counter)
    puts \"#{year}: #{count} dojos\"
  end
"

# グラフデータの確認
rails runner "
  stat = Stat.new(Date.new(2018, 1, 1)..Date.new(2024, 12, 31))
  new_data = stat.annual_new_dojos_count
  new_data.each { |year, count| puts \"#{year}: #{count} new dojos\" }
"

📚 関連ドキュメント

関連

Issue #1373 の解決に向けて、is_active カラムを inactivated_at カラムで
置き換える実装計画を作成。

主な内容:
- 問題の背景と解決策の説明
- カラム名の選択理由(inactivated_at vs deactivated_at)
- 段階的な実装アプローチ(4フェーズ)
- データ移行戦略(Git履歴からの日付抽出)
- 再活性化の扱い(noteカラムを活用)
- 統計への影響と期待される変化

Refs: #1373
@yasulab yasulab self-assigned this Aug 5, 2025
@yasulab yasulab added the 統計情報 Tracking event record function via APIs: https://coderdojo.jp/stats label Aug 5, 2025
yasulab added 10 commits August 6, 2025 14:38
- 2025-08-05時点の道場数の推移データ(2012-2024年)を記録
- 非アクティブ道場を統計に含めた際の影響を測定するために使用
- 追加: docs/dojo_stats_before_inactivated_at_implementation.md
- データベースに inactivated_at カラムを追加(datetime型、インデックス付き)
- note カラムを string から text 型に変更(再活性化履歴の記録用)
- is_active と inactivated_at の同期処理を実装
- active_at スコープを追加(特定時点でのアクティブ道場を取得)
- 基本的なモデルテストを追加

注意: db/dojos.yaml がマスターデータのため、
実際の inactivated_at の永続化にはYAMLファイルの更新が必要
(次のステップで実装予定)

refs #1373
- db/dojos.yaml がマスターレコードであることを明記
- Git履歴抽出はYAMLファイルを直接更新する方式に変更
- データフローを明確化:YAML → DB(rails dojos:update_db_by_yaml)
- Phase 1 の完了をマーク
- Git履歴抽出スクリプトの参考実装を作成
- dojos:update_db_by_yaml への追加方法を確定
- 実装状況とNext Stepsを明確化
Phase 2の実装:
- dojos:update_db_by_yaml タスクに inactivated_at サポートを追加
- Git履歴から inactivated_at を抽出するRakeタスクを作成
  - dojos:extract_inactivated_at_from_git: 全Dojo対象
  - dojos:extract_inactivated_at_for_dojo: 特定Dojo対象
- 統計ロジックを更新して過去の活動履歴を含めるように変更
  - annual_dojos_with_historical_data メソッドを追加
  - 各年末時点でアクティブだったDojo数を正しく集計
- Statモデルのテストを追加

次のステップ:
1. rails dojos:extract_inactivated_at_from_git でYAMLに日付追加
2. rails dojos:update_db_by_yaml でDBに反映
3. ローカルで統計ページの動作確認
- 引数なし: 全ての非アクティブDojoを処理してYAMLを更新
- 引数あり: 特定のDojoの情報を表示のみ(読み取り専用)
- 既に inactivated_at が設定されている場合はスキップ
- コードの重複を排除してメンテナンス性を向上
- add_inactivated_at_to_dojos マイグレーション
- change_note_to_text_in_dojos マイグレーション

の実行結果を反映
- YAMLサポートと統計ロジックの実装が完了
- Phase 3(データ移行とテスト)が次のステップ
- 作業メモや一時ファイルを削除してクリーンアップ
Opus 4.1の詳細レビューにより、以下の改善を実装計画に統合:

主な改善点:
- Phase 3(データ移行)の詳細な実行計画を追加
  - バックアップとベースライン記録スクリプト
  - 事前検証スクリプト(GitExtractionValidator)
  - ドライラン対応の適用スクリプト
- リスク軽減戦略の強化
  - 30分以内のロールバック計画
  - タイムスタンプ付き自動バックアップ
- 成功指標の定量化
  - 測定可能な目標値(完了率100%、精度向上+20%など)
  - 具体的な測定方法を定義
- エッジケースと特殊ケースの対処法を表形式で整理
- パフォーマンス最適化(単一SQLクエリ、キャッシュ戦略)
- モニタリングダッシュボードの実装例

技術的な発見:
- 統計ロジックがカラム存在チェックで自動切り替えする優れた設計
- Git履歴抽出に冪等性が既に実装済み
- Phase 2は実質的に完了状態

実装成功確率: 98%(Opus 4.1評価)

refs #1373
YAMLファイルのGit履歴から、各Dojoがis_active: falseになった
日付を自動抽出してinactivated_atカラムに設定するタスクを実装。

主な機能:
- git blameを使用した変更日時の特定
- YAMLファイルの行番号を正確に検出
- エラーハンドリングと進捗表示
- ドライランモードのサポート

124個中122個のDojoの非活動日を自動抽出することに成功。
@yasulab yasulab changed the title [WIP] Add inactivated_at to Dojo model to replace is_active boolean column Add inactivated_at to Dojo model to replace is_active boolean column Aug 7, 2025
以下のテストを追加:
1. 全ての非アクティブDojoにinactivated_atが設定されていることを確認
2. inactivated_atの日付が妥当であることを検証
   - 正しくパースできる形式
   - 未来の日付でない
   - created_atより後の日付

このテストにより、Rakeタスクで取得した日付の正確性を検証できます。
@yasulab yasulab force-pushed the add-inactivated-at-to-dojo branch from 38aa9f1 to 884afec Compare August 7, 2025 06:47
yasulab added 4 commits August 7, 2025 15:57
問題:
- YAMLファイル更新中に yaml_lines.insert() で行が追加されると
  次のDojoの行番号がずれて git blame が間違った行を参照していた

解決策:
- Phase 1: 全Dojoの情報収集(YAMLを変更せずに)
- Phase 2: 収集した情報を元にYAMLを一括更新
- これにより行番号のずれを防止
Git履歴から抽出した日付を使用して、全ての非アクティブDojoに
活動停止日を記録。これにより統計の精度が向上する。
YAMLファイルのデータ整合性を検証するテスト。
DBではコールバックで自動設定されるが、YAMLファイル(マスターデータ)では
手動編集時にis_activeカラムを忘れる可能性があるため重要。

再活性化されたDojo(is_active: true)の存在も考慮し、
カラムの存在のみをチェック(値は問わない)。
YAMLマスターデータに既にinactivated_atが含まれているため、
条件分岐を削除してシンプルな実装に:

- annual_dojos_with_historical_data で各年末時点の道場数を集計
- HighChartsBuilderでグラフデータを生成
- 統計精度が大幅改善(例:2018年 98→172道場)

テストも簡潔に更新し、全て通過を確認。
@yasulab
Copy link
Member Author

yasulab commented Aug 7, 2025

統計データ周りも大体仕上がったので、一旦ココらでマージ&デプロイします!何かあれば随時追加で修正します...!! 🚀✨

@yasulab yasulab merged commit 86e6f5e into main Aug 7, 2025
5 checks passed
@yasulab yasulab deleted the add-inactivated-at-to-dojo branch August 7, 2025 10:03
yasulab added a commit that referenced this pull request Aug 7, 2025
Cont'd: Add `inactivated_at` to `Dojo` model to replace `is_active` boolean column (#1726)
@yasulab
Copy link
Member Author

yasulab commented Aug 7, 2025

Forgot to git push these commits... 🙈💦 #1731

@yasulab yasulab changed the title Add inactivated_at to Dojo model to replace is_active boolean column 📊 Add inactivated_at to Dojo model to replace is_active boolean column Aug 9, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

統計情報 Tracking event record function via APIs: https://coderdojo.jp/stats

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Dojo モデルに inactived_at を追加し、より正確な統計情報にする

1 participant