Skip to content

Google拡張クライアント用のAPIエンドポイントを作成#9287

Merged
komagata merged 10 commits intofeature/redesign-buzzes-pagefrom
feature/buzz-api-google-extension
Feb 23, 2026
Merged

Google拡張クライアント用のAPIエンドポイントを作成#9287
komagata merged 10 commits intofeature/redesign-buzzes-pagefrom
feature/buzz-api-google-extension

Conversation

@Miya096jp
Copy link
Copy Markdown
Contributor

@Miya096jp Miya096jp commented Nov 1, 2025

Issue

#9253

概要

  • Google拡張機能用のエンドポイントを作成しました。
  • #9102とDBにおいて依存関係があるため、このPRの作業ブランチは#9102のブランチにリベースしています。

作業フェーズ

👉Phase1: Google拡張クライアント用のAPIエンドポイントを作成 #9287
Phase2: BuzzのGoogleExtensionのUIを作成 #1
Phase3: GoogleExtensionとAPI連携

関連Issue

Buzzページのリニューアル#9102

動作確認準備

  1. feature/buzz-api-for-google-extensionをローカルに取り込む
git fetch origin feature/buzz-api-google-extension
git checkout feature/buzz-api-google-extension
  1. foreman start -f Procfile.devでサーバーを起動
  2. 管理者/メンターでログイン
  3. 検証ツールのApplication > cookieからbootcampのcookieをコピーして控える

動作確認

1~5のcurlコマンドをターミナルで実行し、それぞれのレスポンスに、指定の情報が含まれていることを確認してください。

必要に応じて最初にBuzzを削除:

irb(main):001:0> Buzz.delete_all

1. showアクションのテスト1(既存レコードがない場合)

curl -v --get --data-urlencode "url=https://docs.komagata.org/6319" http://localhost:3000/api/buzzes/lookup -b "_bootcamp_session=<cookie>"

レスポンス

  • HTTP/1.1 200 OK
  • {"exists":false}

2. createアクションのテスト1(新規登録)

curl -v -H "Accept: application/json" -H "Content-Type: application/json" -X POST -d '{"buzz": {"title": "buzz_api登録テスト", "url": "https://docs.komagata.org/6319", "published_at": "2025-10-26"}}' http://localhost:3000/api/buzzes -b "_bootcamp_session=<cookie>"

レスポンス
201 created

3. showアクションのテスト2(既存レコードがある場合)

curl -v --get --data-urlencode "url=https://docs.komagata.org/6319" http://localhost:3000/api/buzzes/lookup -b "_bootcamp_session=<cookieをペースト>"

レスポンス

  • 200 OK
  • {"exists":true,"buzz":{"id":1073191923,"created_at":"2025-11-02T14:47:02.079+09:00","updated_at":"2025-11-02T14:47:02.079+09:00","url":"https://docs.komagata.org/6319","title":"buzz_api登録テスト","published_at":"2025-10-26","memo":null}}%

4. createアクションのテスト2(更新)

curl -v -H "Accept: application/json" -H "Content-Type: application/json" -X POST -d '{"buzz": {"title": "buzz_api編集テスト", "url": "https://docs.komagata.org/6319", "published_at": "2025-10-30"}}' http://localhost:3000/api/buzzes -b "_bootcamp_session=<cookie>"

レスポンス

  • 200OK
  • titleとpublished_atが更新されていることを確認
{"buzz": {"title": "buzz_api編集テスト", "url": "https://docs.komagata.org/6319", "published_at": "2025-10-30"}}

5. destroyアクションのテスト

curl -v -X DELETE "http://localhost:3000/api/buzzes/destroy?url=https://docs.komagata.org/6319" -b "_bootcamp_session=<cookie>"

レスポンス
200OK

Summary by CodeRabbit

リリースノート

  • 新機能

    • 紹介・言及記事の閲覧ページを追加。年度別フィルタリングと月ごとのグループ化に対応しました。
    • メンター向け管理画面で、記事の登録・編集・削除が可能になりました。
    • 外部連携用APIエンドポイントを追加。
  • 変更

    • 紹介・言及記事ページのナビゲーションリンクを更新しました。

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Nov 1, 2025

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

概要

このプルリクエストは、Buzzの機能をシングルリソースから複数リソースアーキテクチャに再構築します。本文ベースのコンテンツから、URLベースの参照記事管理に変更します。公開インデックス、メンター管理パネル、APIエンドポイント用に3つのコントローラーを導入し、データベーススキーマを新しい列で拡張します。

変更内容

コホート / ファイル 変更内容
APIコントローラー
app/controllers/api/buzzes_controller.rb
新規作成。checkエンドポイント(URL存在確認)とcreateエンドポイント(Buzzの作成/更新)を実装。管理者またはメンター認証が必須。CSRF保護は無効化。
公開コントローラー
app/controllers/buzzes_controller.rb
新規作成。indexアクション実装。年別フィルタリングと月別グループ化をサポート。
削除されたコントローラー
app/controllers/buzz_controller.rb
削除。旧来のshow/edit/updateアクションをすべて削除。
メンター管理コントローラー
app/controllers/mentor/buzzes_controller.rb
新規作成。フルCRUD操作(index/new/create/edit/update/destroy)実装。URLからのメタデータ抽出機能。
Buzzモデル
app/models/buzz.rb
body検証を削除。title、published_at、url(形式と一意性を検証)の検証を追加。年別フィルタリング、ドキュメント取得、メタデータ抽出用のクラスメソッド追加。Net::HTTP統合。
ヘルパー
app/helpers/buzzes_helper.rb
新規作成。buzzes_by_monthグループ化ロジック実装。
公開ビューテンプレート
app/views/buzzes/index.html.slim
新規作成。年別フィルタリング、月別グループ化、レスポンシブレイアウト実装。
公開ビューパーシャル
app/views/buzzes/_buzz*_filter.html.slim, _buzzes.html.slim
新規作成。PC/モバイル年別フィルター、月別グループ化された記事リスト表示。
削除されたビュー
app/views/buzz/_form.html.slim, show.html.slim
削除。旧来のフォームと表示テンプレート。
メンター管理ビュー
app/views/mentor/buzzes/{index,new,edit}.html.slim, _form.html.slim, _mentor_buzzes.html.slim
新規作成。メンター向けのBuzz管理インターフェース(作成/編集/削除/一覧表示)。
ナビゲーション更新
app/views/layouts/lp/_lp_header.html.slim, app/views/application/_mentor_menu.html.slim, app/views/mentor/_mentor_page_tabs.html.slim
リンク先更新。buzz_path→buzzes_path、edit_buzz_path→mentor_buzzes_path。
ルート設定
config/routes.rb, config/routes/api.rb, config/routes/mentor.rb
単一リソース(resource :buzz)を削除。複数リソース(resources :buzzes)、API routes、メンター namespace routes追加。
CORS設定
config/initializers/cors.rb
新規作成。Chrome拡張機能用CORS設定(/api配下)。
データベース移行
db/migrate/20250828090839_add_columns_to_buzzes.rb 他複数
新規作成。url、title、published_at、memoカラムを追加。bodyカラムを削除。URLに一意インデックス追加。
スキーマ
db/schema.rb
バージョン更新。plpgsql拡張有効化。buzzes テーブル構造変更。
テストサポート
test/supports/buzz_helper.rb
新規作成。Buzzレコード作成ヘルパー(create_buzz、create_buzzes)。
モデルテスト
test/models/buzz_test.rb
新規作成。年別フィルタリング、ドキュメント取得、メタデータ抽出の単体テスト。
システムテスト(新規)
test/system/buzzes_test.rb, test/system/mentor/buzzes_test.rb
新規作成。公開インデックスの年別フィルタリング、メンター管理インターフェース、CRUD操作のエンドツーエンドテスト。
システムテスト(削除)
test/system/buzz_test.rb, test/system/welcome_test.rb
削除。旧来のシステムテスト。
テストフィクスチャ
test/fixtures/buzzes.yml
bodyエントリ削除。
システムテスト設定
test/application_system_test_case.rb
BuzzHelperインクルード追加。

シーケンス図

sequenceDiagram
    participant User as ユーザー
    participant Browser as ブラウザ
    participant PublicCtrl as BuzzesController
    participant Model as Buzzモデル
    participant DB as データベース

    User->>Browser: /buzzes にアクセス
    Browser->>PublicCtrl: GET /buzzes
    PublicCtrl->>Model: Buzz.years
    Model->>DB: SELECT DISTINCT YEAR(published_at)
    DB-->>Model: [2025, 2024, ...]
    PublicCtrl->>Model: Buzz.for_year(year)
    Model->>DB: SELECT * FROM buzzes<br/>WHERE published_at BETWEEN...
    DB-->>Model: buzzes data
    PublicCtrl->>Browser: render index.html.slim<br/>(group_buzzes_by_month)
    Browser-->>User: 月別グループ化された記事表示
Loading
sequenceDiagram
    participant Mentor as メンター
    participant Browser as ブラウザ
    participant MentorCtrl as Mentor::BuzzesController
    participant Model as Buzzモデル
    participant HTTP as 外部URL
    participant DB as データベース

    Mentor->>Browser: /mentor/buzzes/new にアクセス
    Browser->>MentorCtrl: GET /mentor/buzzes/new
    MentorCtrl->>Browser: render new.html.slim (form)
    Mentor->>Browser: URLを入力して送信
    Browser->>MentorCtrl: POST /mentor/buzzes (url param)
    MentorCtrl->>Model: Buzz.doc_from_url(url)
    Model->>HTTP: GET url (HTML fetch)
    HTTP-->>Model: HTML document
    Model->>Model: title_from_doc(doc)<br/>date_from_doc(doc)
    Model-->>MentorCtrl: extracted metadata
    MentorCtrl->>MentorCtrl: populate_buzz_from_doc
    MentorCtrl->>Model: buzz.save
    Model->>DB: INSERT into buzzes
    DB-->>Model: success
    Model-->>MentorCtrl: saved buzz
    MentorCtrl->>Browser: redirect to /mentor/buzzes<br/>(notice: created)
    Browser-->>Mentor: success notice表示
Loading
sequenceDiagram
    participant Extension as Chrome拡張機能
    participant API as API::BuzzesController
    participant Model as Buzzモデル
    participant DB as データベース

    Extension->>API: GET /api/buzzes/check?url=...
    API->>Model: Buzz.find_by(url: ...)
    Model->>DB: SELECT * FROM buzzes<br/>WHERE url = ...
    DB-->>Model: record or nil
    alt URL既存
        Model-->>API: buzz record
        API-->>Extension: {exists: true}
    else URL未登録
        Model-->>API: nil
        API-->>Extension: {exists: false}
    end

    Extension->>API: POST /api/buzzes<br/>{buzz: {url, title, ...}}
    API->>API: require_admin_or_mentor_login
    API->>Model: Buzz.find_or_initialize_by(url: ...)
    alt 新規作成
        Model->>Model: assign attributes
        Model->>DB: INSERT
        DB-->>Model: created
        Model-->>API: saved buzz
        API-->>Extension: {id, url, title, ...}<br/>status: 201
    else 既存更新
        Model->>Model: update attributes
        Model->>DB: UPDATE
        DB-->>Model: updated
        Model-->>API: updated buzz
        API-->>Extension: {id, url, title, ...}<br/>status: 200
    end
Loading

推定レビュー時間

🎯 4 (Complex) | ⏱️ ~45 分

詳細検討が必要な箇所:

  • app/models/buzz.rb: Net::HTTPの統合、URLバリデーション、メタデータ抽出ロジック。エラーハンドリングとタイムアウト処理。
  • app/controllers/mentor/buzzes_controller.rb: URLからのドキュメント取得と属性の自動入力フロー。バリデーションエラーハンドリング。
  • app/controllers/api/buzzes_controller.rb: find_or_initialize_byパターン、新規作成と既存更新の分岐ロジック。権限チェック。
  • config/initializers/cors.rb: Chrome拡張機能ID、CORS設定の セキュリティ検証。
  • データベース移行ファイル: カラム追加、インデックス管理、デフォルト値変更の順序確認。
  • テスト: HTTPスタブ、日付フォーマット、月別グループ化ロジックの正確性。

推奨レビュアー

  • komagata
  • thmz337
  • kushimegu

🐰 Buzzは生まれ変わり
URLの記事、月ごとにきらり
メンターは管理し、API呼ぶ
拡張機能もご機嫌さ
新しき記事たちの舞台へ✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Description check ❓ Inconclusive PR説明では issue番号と概要が記載されていますが、テンプレートで要求される変更確認方法とスクリーンショット(変更前後)が不足しています。 動作確認手順の詳細な説明はありますが、テンプレートの標準形式(## 変更確認方法と## Screenshot)で再整理することを推奨します。
✅ Passed checks (1 passed)
Check name Status Explanation
Title Check ✅ Passed PRタイトル「Google拡張クライアント用のAPIエンドポイントを作成」は、変更セット内の実在する側面を指しており、app/controllers/api/buzzes_controller.rb、config/routes/api.rb、config/initializers/cors.rbにおけるAPIエンドポイント実装というPRの明示的な目的に合致している。ただし、実際の変更内容は#9102(Buzzページリニューアル)に関連する広範な変更を含んでおり、APIエンドポイント作成がPR全体の一部である可能性がある。しかし、PR説明で#9102との依存関係が明記されているため、タイトルは本当の側面を指しており、部分的に関連していると判断できる。
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/buzz-api-google-extension

Tip

Issue Planner is now in beta. Read the docs and try it out! Share your feedback on Discord.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@Miya096jp Miya096jp changed the title Feature/buzz api google extension Google拡張クライアント用のAPIエンドポイントを作成 Nov 1, 2025
@Miya096jp Miya096jp marked this pull request as ready for review November 1, 2025 06:17
@github-actions github-actions Bot requested a review from komagata November 1, 2025 06:17
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (2)
config/initializers/cors.rb (1)

1-9: 拡張機能IDのハードコーディングと環境別の設定を検討してください。

CORS設定は機能的には問題ありませんが、以下の点を確認してください:

  1. 拡張機能IDのハードコーディング: Chrome拡張機能のIDが直接コードに記述されています。開発環境やステージング環境で異なる拡張機能を使用する場合は、環境変数での管理を検討してください。

  2. credentials: true の使用: Cookie/セッションを使用したAPI認証を行う場合は適切ですが、セキュリティ上、クロスオリジンでの認証情報の送信には注意が必要です。

  3. 本番環境での確認: 拡張機能が正式に公開される際、この拡張機能IDが本番用のIDと一致しているか確認してください。

環境変数での管理例:

origins ENV.fetch('CHROME_EXTENSION_ORIGIN', 'chrome-extension://ddobgcfepfdpccmgnpfgjcomccpkcdjj')
app/views/mentor/buzzes/index.html.slim (1)

1-2: メタディスクリプションの追加を検討してください。

タイトルは設定されていますが、set_meta_tagsによるメタディスクリプションが設定されていません。他のメンタービュー(new.html.slimなど)では両方が設定されているため、SEOとページ説明の一貫性のために追加を検討してください。

例:

 - title '紹介・言及記事'
+- set_meta_tags description: 'メンターが管理する紹介・言及記事の一覧ページです。'

Based on learnings

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6d337ef and f351836.

📒 Files selected for processing (41)
  • app/controllers/api/buzzes_controller.rb (1 hunks)
  • app/controllers/buzz_controller.rb (0 hunks)
  • app/controllers/buzzes_controller.rb (1 hunks)
  • app/controllers/mentor/buzzes_controller.rb (1 hunks)
  • app/helpers/buzzes_helper.rb (1 hunks)
  • app/models/buzz.rb (1 hunks)
  • app/views/application/_mentor_menu.html.slim (1 hunks)
  • app/views/buzz/_form.html.slim (0 hunks)
  • app/views/buzz/show.html.slim (0 hunks)
  • app/views/buzzes/_buzz_mobile_filter.html.slim (1 hunks)
  • app/views/buzzes/_buzz_pc_filter.html.slim (1 hunks)
  • app/views/buzzes/_buzzes.html.slim (1 hunks)
  • app/views/buzzes/index.html.slim (1 hunks)
  • app/views/layouts/lp/_lp_header.html.slim (1 hunks)
  • app/views/mentor/_mentor_page_tabs.html.slim (1 hunks)
  • app/views/mentor/buzzes/_form.html.slim (1 hunks)
  • app/views/mentor/buzzes/_mentor_buzzes.html.slim (1 hunks)
  • app/views/mentor/buzzes/edit.html.slim (3 hunks)
  • app/views/mentor/buzzes/index.html.slim (1 hunks)
  • app/views/mentor/buzzes/new.html.slim (1 hunks)
  • config/initializers/cors.rb (1 hunks)
  • config/routes.rb (1 hunks)
  • config/routes/api.rb (1 hunks)
  • config/routes/mentor.rb (1 hunks)
  • db/data/20230726024528_create_buzz.rb (0 hunks)
  • db/migrate/20250828090839_add_columns_to_buzzes.rb (1 hunks)
  • db/migrate/20250829035446_remove_body_from_buzzes.rb (1 hunks)
  • db/migrate/20250830104721_change_default_on_buzzes.rb (1 hunks)
  • db/migrate/20250831044340_add_unique_index_to_buzzes_url_and_title.rb (1 hunks)
  • db/migrate/20250831234516_remove_unique_index_from_buzzes_title.rb (1 hunks)
  • db/migrate/20250831235134_remove_unique_index_from_buzzes_url.rb (1 hunks)
  • db/migrate/20251022075147_add_unique_index_to_buzzes_url.rb (1 hunks)
  • db/schema.rb (2 hunks)
  • test/application_system_test_case.rb (2 hunks)
  • test/fixtures/buzzes.yml (0 hunks)
  • test/models/buzz_test.rb (1 hunks)
  • test/supports/buzz_helper.rb (1 hunks)
  • test/system/buzz_test.rb (0 hunks)
  • test/system/buzzes_test.rb (1 hunks)
  • test/system/mentor/buzzes_test.rb (1 hunks)
  • test/system/welcome_test.rb (0 hunks)
💤 Files with no reviewable changes (7)
  • test/system/welcome_test.rb
  • test/system/buzz_test.rb
  • app/controllers/buzz_controller.rb
  • db/data/20230726024528_create_buzz.rb
  • app/views/buzz/_form.html.slim
  • test/fixtures/buzzes.yml
  • app/views/buzz/show.html.slim
🧰 Additional context used
📓 Path-based instructions (2)
**/*.rb

⚙️ CodeRabbit configuration file

**/*.rb: # refactoring

  • まずFat Controllerを避け、次にFat Modelを避ける。
  • Serviceクラスの乱用を避ける。
  • controller concernを作ろうとしたらPORO(Plain Old Ruby Object)やActiveRecordモデルでの実装で代替できないか検討する。

Rails Patterns

  • ViewHelperにメソッドを実装する時にはまずDecoratorパターンを使うことを検討する。(active_decorator gemを導入しているのでそれを使う)
  • 複雑なActiveRecordクエリがあり、再利用できそうな場合はQueryObjectパターンを検討する。(rails-patterns gemを導入しているのでそれのQuery機能を使う)
  • Viewにpartialを作る場合はViewComponentを使うことを検討する。
  • 複数のActiveRecordモデルを操作する1つの責務がある時や外部APIとやりとりする処理がある場合にはInteractorオブジェクトパターンを検討する。(interactor gemを導入しているのでそれを使う)
  • 複数のInteractorを実行するような処理がある場合Organizerオブジェクトパターンを検討する。(interactor gemを導入しており、その中にOrganizerの機能があるので使う)

Files:

  • app/controllers/buzzes_controller.rb
  • db/migrate/20251022075147_add_unique_index_to_buzzes_url.rb
  • test/application_system_test_case.rb
  • config/routes/mentor.rb
  • db/migrate/20250831234516_remove_unique_index_from_buzzes_title.rb
  • test/system/buzzes_test.rb
  • app/controllers/api/buzzes_controller.rb
  • db/migrate/20250831235134_remove_unique_index_from_buzzes_url.rb
  • db/migrate/20250828090839_add_columns_to_buzzes.rb
  • db/migrate/20250830104721_change_default_on_buzzes.rb
  • test/supports/buzz_helper.rb
  • config/initializers/cors.rb
  • config/routes.rb
  • test/models/buzz_test.rb
  • db/migrate/20250829035446_remove_body_from_buzzes.rb
  • test/system/mentor/buzzes_test.rb
  • app/controllers/mentor/buzzes_controller.rb
  • app/helpers/buzzes_helper.rb
  • db/migrate/20250831044340_add_unique_index_to_buzzes_url_and_title.rb
  • app/models/buzz.rb
  • config/routes/api.rb
  • db/schema.rb
test/**/*

⚙️ CodeRabbit configuration file

test/**/*: # Test

  • TestCase名は英語で書く。
  • どうしても避けられない時以外にsystem testでsleepは使わない。

Unit Test

model, helper, decorator, view_componentについてはメソッドを追加した場合は必ず対応したUnit TestのTestCaseを1つは書く。

Files:

  • test/application_system_test_case.rb
  • test/system/buzzes_test.rb
  • test/supports/buzz_helper.rb
  • test/models/buzz_test.rb
  • test/system/mentor/buzzes_test.rb
🧠 Learnings (14)
📓 Common learnings
Learnt from: Miya096jp
Repo: fjordllc/bootcamp PR: 9102
File: db/migrate/20250831044340_add_unique_index_to_buzzes_url_and_title.rb:3-4
Timestamp: 2025-09-12T00:33:15.034Z
Learning: PR #9102では、Buzzテーブルにユニークインデックスを追加後、同じPR内で削除するというマイグレーションの流れが採用された。これは業務要件でURL/タイトルの重複が許容されるためユニーク制約が不適切だったことによる修正。
Learnt from: komagata
Repo: fjordllc/bootcamp PR: 9101
File: app/notifiers/discord_notifier.rb:131-135
Timestamp: 2025-09-12T21:18:00.834Z
Learning: Rails アップグレードPRにおいて、product_review_not_completed メソッドの webhook URL 設定の shared フォールバック追加も、設定システム全体の変更として別PRで対応すべきである。
📚 Learning: 2025-09-04T01:27:23.422Z
Learnt from: Miya096jp
Repo: fjordllc/bootcamp PR: 9102
File: db/fixtures/buzzes.yml:0-0
Timestamp: 2025-09-04T01:27:23.422Z
Learning: The buzz_controller.rb and related data migration files were deleted as part of the Buzz page redesign, not just modified. The old single buzz page was completely replaced with a new buzzes (plural) listing page with year-based navigation and metadata structure.

Applied to files:

  • app/controllers/buzzes_controller.rb
  • db/migrate/20251022075147_add_unique_index_to_buzzes_url.rb
  • app/views/mentor/_mentor_page_tabs.html.slim
  • test/application_system_test_case.rb
  • config/routes/mentor.rb
  • app/views/mentor/buzzes/_mentor_buzzes.html.slim
  • db/migrate/20250831234516_remove_unique_index_from_buzzes_title.rb
  • app/views/application/_mentor_menu.html.slim
  • app/views/mentor/buzzes/_form.html.slim
  • app/views/layouts/lp/_lp_header.html.slim
  • app/views/mentor/buzzes/new.html.slim
  • test/system/buzzes_test.rb
  • app/controllers/api/buzzes_controller.rb
  • app/views/buzzes/_buzzes.html.slim
  • app/views/mentor/buzzes/index.html.slim
  • db/migrate/20250831235134_remove_unique_index_from_buzzes_url.rb
  • db/migrate/20250828090839_add_columns_to_buzzes.rb
  • db/migrate/20250830104721_change_default_on_buzzes.rb
  • app/views/buzzes/_buzz_pc_filter.html.slim
  • app/views/buzzes/_buzz_mobile_filter.html.slim
  • test/supports/buzz_helper.rb
  • config/routes.rb
  • test/models/buzz_test.rb
  • db/migrate/20250829035446_remove_body_from_buzzes.rb
  • test/system/mentor/buzzes_test.rb
  • app/views/mentor/buzzes/edit.html.slim
  • app/controllers/mentor/buzzes_controller.rb
  • app/helpers/buzzes_helper.rb
  • app/views/buzzes/index.html.slim
  • db/migrate/20250831044340_add_unique_index_to_buzzes_url_and_title.rb
  • app/models/buzz.rb
  • config/routes/api.rb
  • db/schema.rb
📚 Learning: 2025-09-04T01:27:23.422Z
Learnt from: Miya096jp
Repo: fjordllc/bootcamp PR: 9102
File: db/fixtures/buzzes.yml:0-0
Timestamp: 2025-09-04T01:27:23.422Z
Learning: The buzz_controller.rb was indeed deleted, but there are still two remaining items from the old buzz single page implementation that need cleanup: the data migration file db/data/20230726024528_create_buzz.rb and the old buzz route in config/routes.rb line 136. These should be updated/removed to complete the buzz page redesign migration.

Applied to files:

  • app/controllers/buzzes_controller.rb
  • db/migrate/20251022075147_add_unique_index_to_buzzes_url.rb
  • app/views/mentor/_mentor_page_tabs.html.slim
  • test/application_system_test_case.rb
  • config/routes/mentor.rb
  • app/views/mentor/buzzes/_mentor_buzzes.html.slim
  • db/migrate/20250831234516_remove_unique_index_from_buzzes_title.rb
  • app/views/application/_mentor_menu.html.slim
  • app/views/mentor/buzzes/_form.html.slim
  • app/views/layouts/lp/_lp_header.html.slim
  • app/views/mentor/buzzes/new.html.slim
  • test/system/buzzes_test.rb
  • app/controllers/api/buzzes_controller.rb
  • app/views/buzzes/_buzzes.html.slim
  • app/views/mentor/buzzes/index.html.slim
  • db/migrate/20250831235134_remove_unique_index_from_buzzes_url.rb
  • db/migrate/20250828090839_add_columns_to_buzzes.rb
  • db/migrate/20250830104721_change_default_on_buzzes.rb
  • app/views/buzzes/_buzz_pc_filter.html.slim
  • app/views/buzzes/_buzz_mobile_filter.html.slim
  • test/supports/buzz_helper.rb
  • config/routes.rb
  • test/models/buzz_test.rb
  • db/migrate/20250829035446_remove_body_from_buzzes.rb
  • test/system/mentor/buzzes_test.rb
  • app/views/mentor/buzzes/edit.html.slim
  • app/controllers/mentor/buzzes_controller.rb
  • app/helpers/buzzes_helper.rb
  • app/views/buzzes/index.html.slim
  • db/migrate/20250831044340_add_unique_index_to_buzzes_url_and_title.rb
  • app/models/buzz.rb
  • config/routes/api.rb
  • db/schema.rb
📚 Learning: 2025-09-12T00:33:15.034Z
Learnt from: Miya096jp
Repo: fjordllc/bootcamp PR: 9102
File: db/migrate/20250831044340_add_unique_index_to_buzzes_url_and_title.rb:3-4
Timestamp: 2025-09-12T00:33:15.034Z
Learning: PR #9102では、Buzzテーブルにユニークインデックスを追加後、同じPR内で削除するというマイグレーションの流れが採用された。これは業務要件でURL/タイトルの重複が許容されるためユニーク制約が不適切だったことによる修正。

Applied to files:

  • db/migrate/20251022075147_add_unique_index_to_buzzes_url.rb
  • app/views/mentor/buzzes/_mentor_buzzes.html.slim
  • db/migrate/20250831234516_remove_unique_index_from_buzzes_title.rb
  • app/views/layouts/lp/_lp_header.html.slim
  • test/system/buzzes_test.rb
  • app/controllers/api/buzzes_controller.rb
  • app/views/mentor/buzzes/index.html.slim
  • db/migrate/20250831235134_remove_unique_index_from_buzzes_url.rb
  • db/migrate/20250828090839_add_columns_to_buzzes.rb
  • db/migrate/20250830104721_change_default_on_buzzes.rb
  • db/migrate/20250829035446_remove_body_from_buzzes.rb
  • test/system/mentor/buzzes_test.rb
  • app/controllers/mentor/buzzes_controller.rb
  • app/views/buzzes/index.html.slim
  • db/migrate/20250831044340_add_unique_index_to_buzzes_url_and_title.rb
  • app/models/buzz.rb
  • db/schema.rb
📚 Learning: 2025-09-04T01:41:06.709Z
Learnt from: Miya096jp
Repo: fjordllc/bootcamp PR: 9102
File: app/models/buzz.rb:0-0
Timestamp: 2025-09-04T01:41:06.709Z
Learning: Buzzモデルでは、URLとタイトルの重複が業務上発生する可能性があるため、uniqueness制約は使用しない。一度ユニークインデックスを追加したが、重複するケースがあることが判明したため削除された。

Applied to files:

  • db/migrate/20251022075147_add_unique_index_to_buzzes_url.rb
  • db/migrate/20250831234516_remove_unique_index_from_buzzes_title.rb
  • db/migrate/20250831235134_remove_unique_index_from_buzzes_url.rb
  • app/controllers/mentor/buzzes_controller.rb
  • db/migrate/20250831044340_add_unique_index_to_buzzes_url_and_title.rb
  • app/models/buzz.rb
📚 Learning: 2025-09-04T01:50:47.773Z
Learnt from: Miya096jp
Repo: fjordllc/bootcamp PR: 9102
File: db/migrate/20250831234516_remove_unique_index_from_buzzes_title.rb:1-5
Timestamp: 2025-09-04T01:50:47.773Z
Learning: fjordllc/bootcampプロジェクトでは、マイグレーションにおいてdisable_ddl_transaction!やalgorithm: :concurrentlyは使用せず、標準的なRailsのchangeメソッド内でremove_indexを実行する慣例がある。

Applied to files:

  • db/migrate/20251022075147_add_unique_index_to_buzzes_url.rb
  • db/migrate/20250831234516_remove_unique_index_from_buzzes_title.rb
  • db/migrate/20250831235134_remove_unique_index_from_buzzes_url.rb
  • db/migrate/20250831044340_add_unique_index_to_buzzes_url_and_title.rb
📚 Learning: 2025-09-12T01:00:58.452Z
Learnt from: Miya096jp
Repo: fjordllc/bootcamp PR: 9102
File: app/views/mentor/buzzes/edit.html.slim:1-0
Timestamp: 2025-09-12T01:00:58.452Z
Learning: app/views/mentor/buzzes/edit.html.slim では `- title` と `- set_meta_tags` の両方が正しく設定されており、タイトルは削除されていない。変更内容はメタディスクリプションの追加のみ。

Applied to files:

  • app/views/mentor/_mentor_page_tabs.html.slim
  • config/routes/mentor.rb
  • app/views/mentor/buzzes/_mentor_buzzes.html.slim
  • db/migrate/20250831234516_remove_unique_index_from_buzzes_title.rb
  • app/views/application/_mentor_menu.html.slim
  • app/views/mentor/buzzes/_form.html.slim
  • app/views/layouts/lp/_lp_header.html.slim
  • app/views/mentor/buzzes/new.html.slim
  • test/system/buzzes_test.rb
  • app/controllers/api/buzzes_controller.rb
  • app/views/buzzes/_buzzes.html.slim
  • app/views/mentor/buzzes/index.html.slim
  • app/views/buzzes/_buzz_pc_filter.html.slim
  • test/system/mentor/buzzes_test.rb
  • app/views/mentor/buzzes/edit.html.slim
  • app/controllers/mentor/buzzes_controller.rb
  • app/views/buzzes/index.html.slim
  • app/models/buzz.rb
📚 Learning: 2025-08-28T00:34:28.541Z
Learnt from: mousu-a
Repo: fjordllc/bootcamp PR: 8566
File: app/views/application/_global_nav.slim:48-54
Timestamp: 2025-08-28T00:34:28.541Z
Learning: app/views/application/_global_nav.slim のQ&A/ペアワークバッジの環境分岐は、ペアワーク機能の本番リリース後に削除される一時的な実装である。その際、メンター・管理者のみに表示する制限仕様も撤廃される予定のため、現在の実装にはアクセス権限ガードを追加する必要がない。

Applied to files:

  • app/views/mentor/_mentor_page_tabs.html.slim
  • app/views/application/_mentor_menu.html.slim
  • app/views/mentor/buzzes/index.html.slim
  • app/views/mentor/buzzes/edit.html.slim
📚 Learning: 2025-09-04T01:56:02.226Z
Learnt from: Miya096jp
Repo: fjordllc/bootcamp PR: 9102
File: db/migrate/20250831235134_remove_unique_index_from_buzzes_url.rb:1-5
Timestamp: 2025-09-04T01:56:02.226Z
Learning: ExternalEntryモデルはbuzzesテーブルとは無関係で、ユーザーのRSSフィードから外部記事を取得・保存する機能を持つ。ExternalEntry.find_by(url: ...)はbuzzesのURL重複制約とは関係ない。

Applied to files:

  • test/system/buzzes_test.rb
  • app/controllers/api/buzzes_controller.rb
  • test/supports/buzz_helper.rb
  • test/system/mentor/buzzes_test.rb
  • app/controllers/mentor/buzzes_controller.rb
  • app/models/buzz.rb
📚 Learning: 2025-10-22T06:04:36.036Z
Learnt from: sjabcdefin
Repo: fjordllc/bootcamp PR: 9247
File: app/controllers/checks_controller.rb:0-0
Timestamp: 2025-10-22T06:04:36.036Z
Learning: ChecksController#createおよび#destroyでは、Checkの作成・削除とActiveSupport::Notifications.instrumentによるイベント発行(プラクティスのステータス更新)を同一トランザクション内で実行し、いずれかが失敗した場合は両方をロールバックする。これによりWebUI表示とDB状態の整合性を保証している。

Applied to files:

  • app/controllers/api/buzzes_controller.rb
📚 Learning: 2025-09-08T04:55:46.649Z
Learnt from: sharoa119
Repo: fjordllc/bootcamp PR: 8711
File: db/schema.rb:0-0
Timestamp: 2025-09-08T04:55:46.649Z
Learning: In this PR, the removal of length limits from companies.name and companies.website columns in db/schema.rb was unintentional - it was a case of accidentally lost constraints that needed to be restored to their original limits, not a deliberate design change.

Applied to files:

  • db/migrate/20250831235134_remove_unique_index_from_buzzes_url.rb
  • db/migrate/20250828090839_add_columns_to_buzzes.rb
  • db/migrate/20250829035446_remove_body_from_buzzes.rb
  • db/schema.rb
📚 Learning: 2025-06-27T14:06:44.472Z
Learnt from: thmz337
Repo: fjordllc/bootcamp PR: 8857
File: db/migrate/20250624141527_remove_experience_from_users.rb:6-8
Timestamp: 2025-06-27T14:06:44.472Z
Learning: Railsのマイグレーションのdownメソッドでは、元のスキーマの正確な定義を確認してから制約を追加する必要がある。元のカラムに制約がない場合、ロールバック時に制約を追加すると元の状態と異なってしまう。

Applied to files:

  • db/migrate/20250828090839_add_columns_to_buzzes.rb
📚 Learning: 2025-08-31T03:17:44.812Z
Learnt from: mousu-a
Repo: fjordllc/bootcamp PR: 8566
File: db/migrate/20250830033535_add_default_to_pair_works_wip.rb:1-5
Timestamp: 2025-08-31T03:17:44.812Z
Learning: 新機能のマイグレーションで、まだ本番環境にリリースされていない場合は、既存レコードのバックフィル処理は不要。開発環境でrails db:resetが可能な状況では特に、デフォルト値の変更のみで十分。

Applied to files:

  • db/migrate/20250830104721_change_default_on_buzzes.rb
📚 Learning: 2025-07-23T20:42:19.974Z
Learnt from: jun-kondo
Repo: fjordllc/bootcamp PR: 0
File: :0-0
Timestamp: 2025-07-23T20:42:19.974Z
Learning: fjordllc/bootcampプロジェクトでは、hタグ(見出し)の文言は日本語でハードコーディングする方針が確立されており、I18n対応は行わない。例:app/views/welcome/logo.html.slimでh2、h3タグが日本語でハードコーディングされている。

Applied to files:

  • app/views/mentor/buzzes/edit.html.slim
🧬 Code graph analysis (10)
app/controllers/buzzes_controller.rb (1)
app/models/buzz.rb (3)
  • years (28-30)
  • latest_year (24-26)
  • for_year (18-22)
test/application_system_test_case.rb (2)
test/models/user_test.rb (1)
  • include (7-760)
test/test_helper.rb (2)
  • include (22-55)
  • include (57-60)
db/migrate/20250831234516_remove_unique_index_from_buzzes_title.rb (1)
db/migrate/20250831235134_remove_unique_index_from_buzzes_url.rb (2)
  • change (1-5)
  • change (2-4)
test/system/buzzes_test.rb (2)
test/system/mentor/buzzes_test.rb (1)
  • test (6-100)
test/supports/buzz_helper.rb (2)
  • create_buzzes (13-15)
  • create_buzz (4-11)
app/controllers/api/buzzes_controller.rb (1)
app/models/user.rb (1)
  • admin_or_mentor? (660-662)
db/migrate/20250831235134_remove_unique_index_from_buzzes_url.rb (1)
db/migrate/20250831234516_remove_unique_index_from_buzzes_title.rb (2)
  • change (1-5)
  • change (2-4)
test/models/buzz_test.rb (2)
test/supports/buzz_helper.rb (2)
  • create_buzz (4-11)
  • create_buzzes (13-15)
app/models/buzz.rb (6)
  • for_year (18-22)
  • latest_year (24-26)
  • years (28-30)
  • doc_from_url (32-52)
  • title_from_doc (54-56)
  • date_from_doc (58-61)
test/system/mentor/buzzes_test.rb (2)
test/system/buzzes_test.rb (1)
  • test (5-70)
test/supports/buzz_helper.rb (2)
  • create_buzzes (13-15)
  • create_buzz (4-11)
app/controllers/mentor/buzzes_controller.rb (1)
app/models/buzz.rb (3)
  • doc_from_url (32-52)
  • date_from_doc (58-61)
  • title_from_doc (54-56)
app/models/buzz.rb (1)
app/models/metadata.rb (1)
  • parse (16-28)
🔇 Additional comments (36)
config/routes/mentor.rb (1)

23-23: LGTM!

メンター用のBuzzリソースのルーティング定義は適切です。標準的なRESTfulな構成で問題ありません。

db/migrate/20250828090839_add_columns_to_buzzes.rb (1)

3-10: 後続のマイグレーションとの整合性を確認してください。

このマイグレーションでurltitlepublished_atにNOT NULL制約を設定していますが、後続のマイグレーション(20250830104721_change_default_on_buzzes.rb)でこれらのカラムのデフォルト値をnilに変更しています。

NOT NULL制約とデフォルト値nilの組み合わせは、明示的に値を指定せずにレコードを作成しようとした場合にエラーが発生します。アプリケーションコードで常にこれらの値を明示的に指定することを前提としている場合は問題ありませんが、意図した設計かどうかを確認してください。

db/migrate/20250829035446_remove_body_from_buzzes.rb (1)

1-5: LGTM!

Buzzテーブルのbodyカラムの削除は、リニューアルの仕様に沿った変更で問題ありません。

app/helpers/buzzes_helper.rb (1)

4-6: 年をまたいだ場合の動作を確認してください。

現在の実装ではpublished_at.monthのみでグルーピングしているため、異なる年の同じ月(例:2024年1月と2025年1月)が同じグループにまとめられます。

ビューで事前に年でフィルタリングしている場合は問題ありませんが、複数年のデータを同時に表示する可能性がある場合は、以下のように年月でグルーピングすることを検討してください。

def group_buzzes_by_month(buzzes)
  buzzes.group_by { |b| [b.published_at.year, b.published_at.month] }
end

または、年でフィルタリング済みであることをコメントで明記することをお勧めします。

db/migrate/20250831235134_remove_unique_index_from_buzzes_url.rb (1)

1-5: 前のマイグレーションと合わせて見直してください。

このマイグレーションは、20250831044340_add_unique_index_to_buzzes_url_and_title.rbで追加されたユニークインデックスを削除しています。

前述のマイグレーションファイルのレビューコメントで指摘したように、ユニークインデックスの追加と削除の往復は不要です。以下のいずれかの対応を検討してください:

  1. 推奨: ユニークインデックスを追加するマイグレーション(20250831044340)、タイトルのインデックスを削除するマイグレーション(20250831234516)、およびこのマイグレーションをすべて削除する
  2. #9102ブランチから継承されたマイグレーションで既に本番適用済みの場合は、今後の参考として記録する

Based on learnings

⛔ Skipped due to learnings
Learnt from: Miya096jp
Repo: fjordllc/bootcamp PR: 9102
File: db/migrate/20250831044340_add_unique_index_to_buzzes_url_and_title.rb:3-4
Timestamp: 2025-09-12T00:33:15.034Z
Learning: PR #9102では、Buzzテーブルにユニークインデックスを追加後、同じPR内で削除するというマイグレーションの流れが採用された。これは業務要件でURL/タイトルの重複が許容されるためユニーク制約が不適切だったことによる修正。
Learnt from: Miya096jp
Repo: fjordllc/bootcamp PR: 9102
File: db/fixtures/buzzes.yml:0-0
Timestamp: 2025-09-04T01:27:23.422Z
Learning: The buzz_controller.rb was indeed deleted, but there are still two remaining items from the old buzz single page implementation that need cleanup: the data migration file db/data/20230726024528_create_buzz.rb and the old buzz route in config/routes.rb line 136. These should be updated/removed to complete the buzz page redesign migration.
Learnt from: Miya096jp
Repo: fjordllc/bootcamp PR: 9102
File: app/models/buzz.rb:0-0
Timestamp: 2025-09-04T01:41:06.709Z
Learning: Buzzモデルでは、URLとタイトルの重複が業務上発生する可能性があるため、uniqueness制約は使用しない。一度ユニークインデックスを追加したが、重複するケースがあることが判明したため削除された。
Learnt from: Miya096jp
Repo: fjordllc/bootcamp PR: 9102
File: db/fixtures/buzzes.yml:0-0
Timestamp: 2025-09-04T01:27:23.422Z
Learning: The buzz_controller.rb and related data migration files were deleted as part of the Buzz page redesign, not just modified. The old single buzz page was completely replaced with a new buzzes (plural) listing page with year-based navigation and metadata structure.
Learnt from: Miya096jp
Repo: fjordllc/bootcamp PR: 9102
File: db/migrate/20250831234516_remove_unique_index_from_buzzes_title.rb:1-5
Timestamp: 2025-09-04T01:50:47.773Z
Learning: fjordllc/bootcampプロジェクトでは、マイグレーションにおいてdisable_ddl_transaction!やalgorithm: :concurrentlyは使用せず、標準的なRailsのchangeメソッド内でremove_indexを実行する慣例がある。
Learnt from: sharoa119
Repo: fjordllc/bootcamp PR: 9012
File: db/migrate/20250905025850_remove_redundant_index_from_reports.rb:5-5
Timestamp: 2025-09-05T03:33:31.659Z
Learning: reports テーブルには既存の一意制約インデックス index_reports_on_user_id_and_reported_on があるため、同じカラム組み合わせ (user_id, reported_on) の非一意インデックスは冗長であり削除が適切。一意制約インデックスは非一意インデックスと同等かそれ以上のクエリ性能を提供する。
Learnt from: sharoa119
Repo: fjordllc/bootcamp PR: 9012
File: db/migrate/20250905025850_remove_redundant_index_from_reports.rb:5-5
Timestamp: 2025-09-05T03:33:31.659Z
Learning: reports テーブルには既存の一意制約インデックス index_reports_on_user_id_and_reported_on があるため、同じカラム組み合わせ (user_id, reported_on) の非一意インデックスは冗長であり削除が適切。
Learnt from: Miya096jp
Repo: fjordllc/bootcamp PR: 9102
File: app/views/mentor/buzzes/edit.html.slim:1-0
Timestamp: 2025-09-12T01:00:58.452Z
Learning: app/views/mentor/buzzes/edit.html.slim では `- title` と `- set_meta_tags` の両方が正しく設定されており、タイトルは削除されていない。変更内容はメタディスクリプションの追加のみ。
Learnt from: komagata
Repo: fjordllc/bootcamp PR: 9101
File: app/notifiers/discord_notifier.rb:131-135
Timestamp: 2025-09-12T21:18:00.834Z
Learning: Rails アップグレードPRにおいて、product_review_not_completed メソッドの webhook URL 設定の shared フォールバック追加も、設定システム全体の変更として別PRで対応すべきである。
Learnt from: sharoa119
Repo: fjordllc/bootcamp PR: 9012
File: app/queries/grass_learning_time_query.rb:30-37
Timestamp: 2025-09-05T03:16:53.387Z
Learning: reports テーブルには既に (user_id, reported_on) の一意制約インデックス index_reports_on_user_id_and_reported_on が存在するため、学習時間集計クエリのパフォーマンス最適化には追加のインデックスは不要。
db/migrate/20250831234516_remove_unique_index_from_buzzes_title.rb (1)

1-5: マイグレーションの実装は正しい。

このマイグレーションは基盤ブランチ#9102由来のファイルで、プロジェクトの慣例に従った標準的な実装です。changeメソッドは可逆的で、remove_indexの実行方法もプロジェクトの規約に沿っています。

Based on learnings

app/views/mentor/buzzes/_mentor_buzzes.html.slim (1)

1-27: 実装は適切です。

メンター用のBuzz一覧パーシャルが正しく実装されています。セキュリティ対策(rel: 'noopener noreferrer')、日付のローカライゼーション(l())、アクセシビリティ(説明的なリンクテキスト)が適切に考慮されています。

app/views/application/_mentor_menu.html.slim (1)

26-26: リンク先の更新は正しい。

単数形リソースから複数形リソースへの移行に合わせて、リンク先がbuzzes_pathに更新されています。他のヘッダーファイルの変更とも一貫性があります。

db/migrate/20251022075147_add_unique_index_to_buzzes_url.rb (1)

1-5: URL単位のユニーク制約は適切です。

このマイグレーションは、タイトルのユニーク制約を削除した後、URLのみにユニーク制約を追加しています。学習内容によると、業務要件ではタイトルの重複が許容されるため、URL単位でのユニーク性確保は妥当な設計です。

Based on learnings

app/views/layouts/lp/_lp_header.html.slim (1)

40-40: ナビゲーションリンクの更新は正しい。

LPヘッダーのリンク先もbuzzes_pathに更新されており、他のナビゲーションコンポーネントとの一貫性が保たれています。

app/views/mentor/buzzes/new.html.slim (1)

1-30: ビューの実装は適切です。

メンター用のBuzz作成ページが正しく実装されています。タイトルとメタタグの設定、ナビゲーション構造、フォームパーシャルへの委譲が適切に行われており、他のメンタービューとの一貫性も保たれています。

test/application_system_test_case.rb (1)

16-16: テストヘルパーの追加は適切です。

BuzzHelperの追加は、他のヘルパー(ProductHelperAvatarHelperなど)と同じパターンに従っており、システムテストでのBuzzデータのセットアップを可能にします。

Also applies to: 31-31

app/views/mentor/buzzes/index.html.slim (1)

3-41: ページ構造とナビゲーションは適切です。

メンター用のBuzz一覧ページが正しく実装されています。記事登録とページ表示のアクションボタン、ページネーション、パーシャルのレンダリングが適切に配置されています。外部リンクにはtarget: '_blank'rel: 'noopener'が正しく設定されています。

app/views/mentor/_mentor_page_tabs.html.slim (1)

26-27: 変更内容を確認しました。

メンター用のBuzzページへのパス更新が正しく行われています。mentor_buzzes_pathへのリンクと、対応する正規表現/^mentor-buzzes/の変更は一貫性があります。

app/views/buzzes/_buzz_mobile_filter.html.slim (1)

1-13: モバイルフィルターの実装を確認しました。

年選択フィルターのUI実装は適切です。フォームの送信とパラメータの処理が正しく行われています。

app/views/mentor/buzzes/edit.html.slim (3)

2-2: メタディスクリプションの追加を確認しました。

SEO対策として適切な追加です。


24-25: メンター用Buzzページへのリンクが正しく更新されています。

mentor_buzzes_pathへの変更と、is-backクラスの追加により、一貫したUI/UXが提供されています。


30-30: 削除ボタンの実装を確認しました。

確認ダイアログ付きの削除ボタンが適切に実装されています。

app/views/buzzes/_buzzes.html.slim (1)

1-13: Buzzの月別グループ表示実装を確認しました。

  • 月別グルーピングのヘルパーメソッド使用が適切です
  • メンター向けの編集リンクの条件表示が正しく実装されています
  • 外部リンクのセキュリティ属性(noopener noreferrer)が適切に設定されています
app/controllers/buzzes_controller.rb (1)

4-10: Buzzインデックスアクションの実装を確認しました。

年別フィルタリングとソートロジックが正しく実装されています。published_at降順、次にid降順のソートにより、同日公開の記事も一貫した順序で表示されます。

test/system/mentor/buzzes_test.rb (1)

1-100: メンター用Buzzシステムテストの実装を確認しました。

CRUD操作のテストカバレッジが適切です。外部リクエストのスタブ処理も正しく実装されています。テストケース名も英語で記述されており、コーディングガイドラインに準拠しています。

PR目的に記載の通り、Google拡張機能用のAPIエンドポイント(API::BuzzesControllercheckおよびcreateアクション)に対する自動テストは、拡張機能完成後に別PRで追加予定とのことですが、このことを確認してください。現在のPRではAPIエンドポイントのテストが含まれていません。

test/supports/buzz_helper.rb (1)

3-16: テストヘルパーの実装を確認しました。

BuzzHelperモジュールの実装が適切です:

  • create!を使用して検証エラー時に明示的に失敗
  • URLの重複を避けるためSecureRandom.hex(4)を使用
  • オプション引数でカスタマイズ可能な柔軟な設計
config/routes/api.rb (1)

91-92: 22行目の full_messagefull_messages に修正が必要です。

実装確認結果:対応するAPIコントローラーは存在し、基本的な実装はすべて揃っています。ただし、createアクションの更新失敗時レスポンス処理に typo があります。

@buzz.errors.full_message は存在しないメソッドで、正しくは @buzz.errors.full_messages(複数形)です。このバグは既存 Buzz の更新が失敗した場合に実行され、エラーが発生します。

⛔ Skipped due to learnings
Learnt from: Miya096jp
Repo: fjordllc/bootcamp PR: 9102
File: db/fixtures/buzzes.yml:0-0
Timestamp: 2025-09-04T01:27:23.422Z
Learning: The buzz_controller.rb was indeed deleted, but there are still two remaining items from the old buzz single page implementation that need cleanup: the data migration file db/data/20230726024528_create_buzz.rb and the old buzz route in config/routes.rb line 136. These should be updated/removed to complete the buzz page redesign migration.
Learnt from: Miya096jp
Repo: fjordllc/bootcamp PR: 9102
File: db/migrate/20250831044340_add_unique_index_to_buzzes_url_and_title.rb:3-4
Timestamp: 2025-09-12T00:33:15.034Z
Learning: PR #9102では、Buzzテーブルにユニークインデックスを追加後、同じPR内で削除するというマイグレーションの流れが採用された。これは業務要件でURL/タイトルの重複が許容されるためユニーク制約が不適切だったことによる修正。
Learnt from: Miya096jp
Repo: fjordllc/bootcamp PR: 9102
File: db/fixtures/buzzes.yml:0-0
Timestamp: 2025-09-04T01:27:23.422Z
Learning: The buzz_controller.rb and related data migration files were deleted as part of the Buzz page redesign, not just modified. The old single buzz page was completely replaced with a new buzzes (plural) listing page with year-based navigation and metadata structure.
Learnt from: ryufuta
Repo: fjordllc/bootcamp PR: 9155
File: app/controllers/api/correct_answers_controller.rb:20-22
Timestamp: 2025-09-15T07:39:39.350Z
Learning: API::CorrectAnswersController#update では、ベストアンサー取り下げという単純な状態変更のため、update! を使用して DB エラー時に 500 を返し、成功時はデフォルトレスポンスを使用するのが適切。クライアント側のバリデーションエラーは発生しにくく、明示的なエラーハンドリングは不要。
Learnt from: Miya096jp
Repo: fjordllc/bootcamp PR: 9102
File: app/views/mentor/buzzes/edit.html.slim:1-0
Timestamp: 2025-09-12T01:00:58.452Z
Learning: app/views/mentor/buzzes/edit.html.slim では `- title` と `- set_meta_tags` の両方が正しく設定されており、タイトルは削除されていない。変更内容はメタディスクリプションの追加のみ。
Learnt from: komagata
Repo: fjordllc/bootcamp PR: 9101
File: app/notifiers/discord_notifier.rb:131-135
Timestamp: 2025-09-12T21:18:00.834Z
Learning: Rails アップグレードPRにおいて、product_review_not_completed メソッドの webhook URL 設定の shared フォールバック追加も、設定システム全体の変更として別PRで対応すべきである。
Learnt from: sjabcdefin
Repo: fjordllc/bootcamp PR: 9247
File: app/controllers/checks_controller.rb:0-0
Timestamp: 2025-10-22T06:04:36.036Z
Learning: ChecksController#createおよび#destroyでは、Checkの作成・削除とActiveSupport::Notifications.instrumentによるイベント発行(プラクティスのステータス更新)を同一トランザクション内で実行し、いずれかが失敗した場合は両方をロールバックする。これによりWebUI表示とDB状態の整合性を保証している。
Learnt from: Miya096jp
Repo: fjordllc/bootcamp PR: 9102
File: app/controllers/mentor/buzzes_controller.rb:0-0
Timestamp: 2025-09-04T01:39:22.261Z
Learning: fjordllc/bootcamp プロジェクトでは、更新処理の成功時の通知メッセージについて、I18n を使用せずに日本語文字列を直接記述する方針で一貫性を保っている。
Learnt from: komagata
Repo: fjordllc/bootcamp PR: 9101
File: app/notifiers/discord_notifier.rb:19-23
Timestamp: 2025-09-12T21:17:26.029Z
Learning: Rails アップグレードPRにおいて、config_for(:secrets) を使った webhook URL 設定の shared セクション未参照問題は、設定システム全体の変更として別PRで対応すべきである。
Learnt from: jun-kondo
Repo: fjordllc/bootcamp PR: 8977
File: app/controllers/reports_controller.rb:63-63
Timestamp: 2025-07-23T20:31:13.856Z
Learning: fjordllc/bootcampプロジェクトの`app/controllers/reports_controller.rb`において、`create`と`update`アクションは両方とも`report.save_uniquely`を使用し、同じ`:report_save`イベントと`'report.save'`イベントを発行する。これは両方とも本質的に「レポートの保存」操作であり、作成と更新を区別する必要がないためである。
app/views/mentor/buzzes/_form.html.slim (1)

1-33: LGTM!

メンター用のBuzz管理フォームの実装が適切です。新規作成時のみURLフィールドを表示する条件分岐(Line 11)や、タイトルの自動取得を示すプレースホルダーなど、ユーザー体験を考慮した設計になっています。

app/views/buzzes/_buzz_pc_filter.html.slim (1)

1-7: LGTM!

年別フィルターの実装が適切です。パラメータからのアクティブ年の取得と、年の降順表示が正しく実装されています。

app/views/buzzes/index.html.slim (1)

1-54: LGTM!

Buzzの一覧ページの実装が適切です。ページタイトル、メタタグ、年別フィルター、記事一覧の表示、そして管理者・メンター向けの編集リンクが適切に実装されています。

test/models/buzz_test.rb (1)

1-91: テストカバレッジが適切です。

Buzzモデルの主要メソッド(年別フィルタ、URL取得、パース処理)に対するテストが網羅されています。HTTPスタブとNokogiriを使った適切なテスト実装になっています。

config/routes.rb (1)

135-136: LGTM!

Buzzの複数形リソースルートへの変更が適切に実装されています。年別フィルタリング用のカスタムルート(Line 135)と、インデックスのみを許可するリソースルート(Line 136)の組み合わせが適切です。

db/schema.rb (1)

114-122: LGTM!

Buzzesテーブルのスキーマ変更が適切です。URL、タイトル、公開日を必須フィールドとし、URLにユニークインデックスを追加することで、Google拡張機能からのAPI利用に適した構造になっています。

app/controllers/api/buzzes_controller.rb (3)

7-15: LGTM!

URLの存在確認エンドポイントの実装が適切です。バリデーション(Line 8)と存在確認(Line 10)が正しく実装されています。


17-27: find_or_initialize_byを使用した適切なupsertパターンです。

Line 20でfind_or_initialize_byを使用することで、新規作成と更新を適切に処理しています。エラーハンドリングも適切です。


37-41: LGTM!

API用の認可チェックが適切に実装されています。管理者またはメンターのみがアクセスできるように制限されています。

app/controllers/mentor/buzzes_controller.rb (4)

18-37: URL取得とバリデーションの実装が適切です。

createアクションでURLの存在確認(Line 21)、URLからのドキュメント取得(Line 23)、取得失敗時のエラー処理(Lines 25-28)が適切に実装されています。ユーザーに分かりやすいエラーメッセージも表示されます。


54-69: LGTM!

populate_buzz_from_docメソッドの実装が適切です。タイトルと公開日をドキュメントから抽出し、適切なバリデーションとエラー処理を行っています。


84-88: セキュリティを考慮した優れた実装です。

Line 86で:urlパラメータをcreateアクション時のみ許可することで、更新時にURLが変更されることを防いでいます。これはURLがユニークキーとして使用されているため、適切なセキュリティ対策です。


8-10: LGTM!

Buzzの一覧表示が適切に実装されています。published_atidの降順でソートすることで、最新の記事が優先的に表示され、同じ日付の場合も一貫した順序が保証されます。

Comment thread app/controllers/api/buzzes_controller.rb
Comment thread app/models/buzz.rb Outdated
Comment thread db/migrate/20250830104721_change_default_on_buzzes.rb
Comment thread db/migrate/20250831044340_add_unique_index_to_buzzes_url_and_title.rb Outdated
Comment thread test/models/buzz_test.rb
@Miya096jp Miya096jp changed the base branch from main to feature/redesign-buzzes-page November 1, 2025 06:23
@Miya096jp Miya096jp force-pushed the feature/buzz-api-google-extension branch from f351836 to 9fefbac Compare November 1, 2025 06:36
@Miya096jp Miya096jp self-assigned this Nov 1, 2025
@Miya096jp
Copy link
Copy Markdown
Contributor Author

@komagata

お疲れ様です!
Google拡張のIssueのPhase1になります。
レビューをお願いいたします🙇🏻‍♂️

before_action :require_admin_or_mentor_login_for_api
skip_before_action :verify_authenticity_token

def check
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RESTfulなアクションだけで構成したほうがいいと思います。

参考:DHHはどのようにRailsのコントローラを書くのか | POSTD

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@komagata

資料ありがとうございます、理解した上で修正しました。
あらためてbootcampのコントローラーを見て、見る限りすべてRESTfulなアクションを使っていることに気がつきました。

@Miya096jp Miya096jp force-pushed the feature/buzz-api-google-extension branch 2 times, most recently from 18afc91 to 7511d5c Compare November 5, 2025 11:36
Comment thread app/controllers/api/base_controller.rb Outdated
User.find(doorkeeper_token.resource_owner_id) if doorkeeper_token
end

def require_admin_or_mentor_login_for_api
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

こちらに書くほうがよいとおもいます。

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@komagata

concernsに移動しました。

@@ -0,0 +1,17 @@
# frozen_string_literal: true

class API::Buzzes::LookupsController < API::BaseController
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

クラス名(リソース名)は名詞である必要があります。(メソッドが動詞)

@Miya096jp Miya096jp force-pushed the feature/redesign-buzzes-page branch 2 times, most recently from bc37e35 to 0ede869 Compare November 26, 2025 08:44
@Miya096jp Miya096jp force-pushed the feature/redesign-buzzes-page branch 10 times, most recently from 01ca037 to 4221566 Compare December 21, 2025 07:08
@Miya096jp Miya096jp force-pushed the feature/redesign-buzzes-page branch 4 times, most recently from b36e7d5 to d3e8f53 Compare December 22, 2025 06:57
@Miya096jp Miya096jp force-pushed the feature/redesign-buzzes-page branch 2 times, most recently from 7d750d9 to 2ffaf9d Compare February 10, 2026 02:01
@Miya096jp
Copy link
Copy Markdown
Contributor Author

@komagata

お疲れ様です!
長らく放置してしまい、大変申し訳ございません。
改めて見直してみて、分割したコントローラーをまとめるなど、大きく修正をおこなしました。
ご確認をお願いいたします🙇🏻‍♂️

@komagata
Copy link
Copy Markdown
Member

@Miya096jp conflictの解消をおねがいします。

@Miya096jp Miya096jp force-pushed the feature/buzz-api-google-extension branch 2 times, most recently from a879ca8 to f41ebeb Compare February 16, 2026 01:38
@Miya096jp
Copy link
Copy Markdown
Contributor Author

@komagata

Chrome拡張のクライアント側の作業と同時進行していたため、こちらあろうことかpushをし忘れてレビュー依頼をしておりました。ワークフローを見直します。申し訳ございません。

head :not_found
end
end

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

もともとコントローラーを分割していましたが、時間が経って見てみると統合した方が自然かなと思うようになりました。理由としては、当初コードを書いているとき、私がshowアクションに対してクエリーパラメーターをつけてリクエストする、ということに「意味的に変なのでは?」と違和感を感じて、lookupカスタムアクションを定義し、その後アドバイスを頂いて分割しました。時間が経って見てみると、今回のケースの場合、「分けるんだったらこうしたがいいよ」ということで、そもそも普通のshowアクションでもOKなのかなと感じるようになり、今回まとめてみました。適切でなければまた分割をしますので、ご確認お願いいたします。

@komagata
Copy link
Copy Markdown
Member

@Miya096jp 「APIエンドポイントを作成」であればviewやcssには変更がないPRが自然かなと思いました。

クローズした#9283の指摘を受けてエラーハンドリングを追加
StrongParameterにurlを含めるように変更
RESTfulな構成にするためにコントローラーを分割しcheckアクションを移設・修正
- destroyアクションのリソースをurlでクエリーするため
-
destroyアクションのelse句の構文エラーを修正し、正しく404が返却されるようにした
- lookups_controllerからbuzz_controllerに名前変更/クライアントも合わせて修正し動作確認済み
@Miya096jp Miya096jp force-pushed the feature/buzz-api-google-extension branch from f41ebeb to 0263114 Compare February 20, 2026 11:39
@Miya096jp
Copy link
Copy Markdown
Contributor Author

@komagata

ヒント出して頂いてありがとうございます!ようやく理解しました😱
親ブランチの最新に合わせ、cherry-pickしました。

Copy link
Copy Markdown
Member

@komagata komagata left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

確認させていただきました。OKです〜🙆‍♂️

@komagata komagata merged commit 590c36c into feature/redesign-buzzes-page Feb 23, 2026
4 checks passed
@komagata komagata deleted the feature/buzz-api-google-extension branch February 23, 2026 07:26
@Miya096jp
Copy link
Copy Markdown
Contributor Author

@komagata

ありがとうございます!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants