-
Notifications
You must be signed in to change notification settings - Fork 75
給付金コースのプラクティスの関連日報一覧に元コースの関連日報を表示切替のフィルターを追加 #9515
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
📝 WalkthroughWalkthrough給付金コース向けの日報フィルタリング機能を追加します。バックエンド(スコープとAPIエンドポイント)とフロントエンド(給付金フィルターUIコンポーネント)を実装し、ユーザーがアクティブなコースの日報を段階的にフィルタリング可能にしました。 Changes
Sequence Diagram(s)sequenceDiagram
actor User
participant Reports as Reports.jsx
participant Filter as grant-filter.js
participant API as API /reports
participant DB as Database
User->>Reports: Load reports with practiceSourceId
Reports->>Filter: useEffect: Dynamically load grant filter
Filter->>Filter: render() & initialize tab state
User->>Filter: Click grant filter tab
Filter->>Filter: Update withGrant state
Filter->>Reports: setWithGrant callback
Reports->>API: Fetch with with_grant query param
API->>DB: Apply with_grant_practices scope
DB-->>API: Return filtered reports
API-->>Reports: Return results
Reports->>Reports: Re-render with filtered data
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~22 minutes Possibly related issues
Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
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. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🤖 Fix all issues with AI agents
In `@app/javascript/grant-filter.js`:
- Around line 9-21: The template string in render(element) contains a malformed
closing tag `</nav` (missing the trailing '>') which breaks HTML parsing; update
the template literal in the render(element) method (in grant-filter.js) to use a
proper closing `</nav>` tag so the generated markup is valid.
In `@db/fixtures/users.yml`:
- Around line 1559-1577: The name_kana field is set in kanji instead of
katakana; update the fixture entry for login_name grant-course by replacing
name_kana: 給付金コースのユーザー with the katakana form (e.g. name_kana: キュウフキンコースノユーザー)
so it matches other user fixtures and maintains consistency with name:
給付金コースのユーザー.
🧹 Nitpick comments (3)
.rubocop.yml (1)
31-34: 複雑度の除外設定について検討が必要です。
Metrics/PerceivedComplexityの除外は、コントローラーの複雑度が増したことへの対応として理解できます。ただし、RuboCop の警告を除外するよりも、コントローラーのロジックをリファクタリングする方が望ましい場合があります。例えば、フィルタリングロジックを Query Object パターン(rails-patterns gem)やスコープチェーンを返す専用メソッドに抽出することで、複雑度を下げられる可能性があります。コーディングガイドラインでは、複雑な ActiveRecord クエリには QueryObject パターンの検討が推奨されています。
現時点では問題ありませんが、将来的なリファクタリングの候補として検討してください。
app/models/report.rb (1)
64-66: スコープのロジックは正しいですが、クエリの効率化を検討してください。このスコープは、
source_idがnilのプラクティスを持つ日報を除外することで、給付金コースの日報のみを取得します。ロジック自体は正しいです。ただし、サブクエリを使用しているため、データ量が増えた場合にパフォーマンスへの影響が考えられます。将来的には
NOT EXISTSを使ったアプローチも検討できます:♻️ 代替案(参考)
scope :with_grant_practices, lambda { joins(:practices) .where.not( Practice.joins(:reports) .where('reports.id = reports_practices.report_id') .where(source_id: nil) .arel.exists ) .distinct }または
where.associatedと組み合わせたアプローチも可能です。現時点では問題ありませんが、将来のパフォーマンス最適化の候補としてご検討ください。
app/javascript/components/Reports.jsx (1)
37-57:useEffectの依存配列にdataを含める必要性を確認してください。
dataを依存配列に含めると、データが取得されるたびに effect が再実行され、grant filter が再レンダリングされます。これは意図的な動作かもしれませんが(DOM要素が存在するのを待つため)、isGrantCourseが変更されない限り、filter UIを再初期化する必要はないはずです。また、
isGrantCourseはpracticeSourceIdから派生していますが、依存配列には含まれていません。ESLintのreact-hooks/exhaustive-depsルールに従うなら、isGrantCourseまたはpracticeSourceIdを依存配列に追加することを検討してください。♻️ 検討案
useEffect(() => { if (!isGrantCourse) return let grantFilter = null const initGrantFilter = async () => { const targetElement = document.querySelector('[data-grant-filter]') if (!targetElement) return const GrantFilter = (await import('../grant-filter')).default grantFilter = new GrantFilter(withGrant, setWithGrant) grantFilter.render(targetElement) } initGrantFilter() return () => { if (grantFilter) { grantFilter.destroy() grantFilter = null } } - }, [data, withGrant]) + }, [isGrantCourse, withGrant])
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (11)
.rubocop.ymlapp/controllers/api/reports_controller.rbapp/javascript/components/Reports.jsxapp/javascript/grant-filter.jsapp/models/report.rbapp/views/practices/reports/index.html.slimdb/fixtures/courses_categories.ymldb/fixtures/discord_profiles.ymldb/fixtures/reports.ymldb/fixtures/talks.ymldb/fixtures/users.yml
💤 Files with no reviewable changes (1)
- db/fixtures/courses_categories.yml
🧰 Additional context used
📓 Path-based instructions (5)
app/**/*.rb
📄 CodeRabbit inference engine (AGENTS.md)
app/**/*.rb: Place Rails app code inapp/directory with subdirectories formodels/,controllers/,views/,jobs/,helpers/, and frontend code underjavascript/
Follow Rails file naming conventions (e.g.,app/models/user.rb)
Files:
app/controllers/api/reports_controller.rbapp/models/report.rb
**/*.rb
📄 CodeRabbit inference engine (AGENTS.md)
Use 2-space indent for Ruby code, snake_case for method names, and CamelCase for class names as enforced by RuboCop
Files:
app/controllers/api/reports_controller.rbapp/models/report.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/api/reports_controller.rbapp/models/report.rb
app/views/**/*.slim
📄 CodeRabbit inference engine (AGENTS.md)
Place Slim templates in
app/views/and ensure they are linted according toconfig/slim_lint.yml
Files:
app/views/practices/reports/index.html.slim
app/javascript/**/*.{js,ts,jsx,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
app/javascript/**/*.{js,ts,jsx,tsx}: Place JavaScript/TypeScript code inapp/javascript/and lint with ESLint + Prettier
Use React 18 and Shakapacker/Webpack 5 for frontend JavaScript/TypeScript
Files:
app/javascript/grant-filter.jsapp/javascript/components/Reports.jsx
**/*.js
⚙️ CodeRabbit configuration file
**/*.js: - どうしても避けられない時以外に新規にVue.js, Reactのコードを追加しない。
- fetchメソッドの代わりにrequest.jsを使う。
Files:
app/javascript/grant-filter.js
🧠 Learnings (7)
📓 Common learnings
Learnt from: komagata
Repo: fjordllc/bootcamp PR: 9101
File: app/models/graduation_notifier.rb:23-28
Timestamp: 2025-09-12T21:16:47.639Z
Learning: Rails upgrade PRにおいて、configuration systemの変更やwebhook設定の改善提案も、アップグレードに直接関連しない場合は別PRで対応すべきである。PRのスコープ維持が重要。
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: komagata
Repo: fjordllc/bootcamp PR: 9101
File: app/models/product.rb:59-61
Timestamp: 2025-09-11T14:47:53.256Z
Learning: Rails アップグレードPRでは、アップグレードに直接関連しない性能改善や機能追加の提案は避けるべき。PRのスコープを維持することが重要で、そのような改善提案は別PRで対応すべきである。
Learnt from: ryufuta
Repo: fjordllc/bootcamp PR: 8992
File: app/models/correct_answer_notifier.rb:23-23
Timestamp: 2025-07-30T07:26:36.599Z
Learning: PRのスコープを維持することが重要であり、バグ修正PRにおいて、修正対象以外の機能(例:ルーティングテスト)の追加提案は適切ではない。そのような改善が必要な場合は別PRで対応すべきである。
Learnt from: smallmonkeykey
Repo: fjordllc/bootcamp PR: 9314
File: app/helpers/page_tabs/dashboard_helper.rb:8-12
Timestamp: 2025-11-19T07:55:51.504Z
Learning: fjordllc/bootcamp プロジェクトにおいて、分報(micro_reports)は current_user 専用の機能ではなく、他ユーザーの分報も閲覧・管理する UI で使われているため、ダッシュボードの「自分の分報」タブでは user_micro_reports_path(current_user, ...) を使用し、/users/:id/micro_reports の URL 構造を維持する。current_user 名前空間に新しいルートを追加しない方針である。
Learnt from: komagata
Repo: fjordllc/bootcamp PR: 9101
File: app/notifiers/discord_notifier.rb:52-56
Timestamp: 2025-09-12T21:17:45.295Z
Learning: Rails upgrade PRにおいて、configuration systemの改善提案(shared configuration fallback等)も、アップグレードに直接関連しない場合は別PRで対応すべきである。PRのスコープ維持が重要。
📚 Learning: 2026-01-08T21:12:18.350Z
Learnt from: mousu-a
Repo: fjordllc/bootcamp PR: 8566
File: app/controllers/pair_works_controller.rb:10-18
Timestamp: 2026-01-08T21:12:18.350Z
Learning: In fjordllc/bootcamp, when using ActiveRecord.order to specify ascending order, omit the explicit :asc and rely on Rails' default ASC behavior. Prefer .order(:published_at) over .order(published_at: :asc). If you need a non-default order (e.g., DESC), specify it explicitly. This guideline applies to Ruby/Rails controller and model files, especially in app/controllers and similar ActiveRecord usage sites.
Applied to files:
app/controllers/api/reports_controller.rb
📚 Learning: 2025-08-24T13:40:16.118Z
Learnt from: sjabcdefin
Repo: fjordllc/bootcamp PR: 9090
File: app/javascript/user_sns.js:36-45
Timestamp: 2025-08-24T13:40:16.118Z
Learning: app/javascript/user_sns.js では baseUrl は固定値、url は db/fixtures/users.yml で定義されているフィクスチャデータを使用している
Applied to files:
db/fixtures/users.yml
📚 Learning: 2025-08-24T13:40:16.118Z
Learnt from: sjabcdefin
Repo: fjordllc/bootcamp PR: 9090
File: app/javascript/user_sns.js:36-45
Timestamp: 2025-08-24T13:40:16.118Z
Learning: app/javascript/user_sns.js で使用される SNS フィールド(github_account, twitter_account, facebook_url, blog_url)は db/fixtures/users.yml の読み取り専用データで、ユーザーや管理者による編集機能は存在しない
Applied to files:
db/fixtures/users.yml
📚 Learning: 2026-01-11T04:41:41.597Z
Learnt from: mousu-a
Repo: fjordllc/bootcamp PR: 8566
File: app/views/pair_works/_body.html.slim:95-100
Timestamp: 2026-01-11T04:41:41.597Z
Learning: Ruby 3.1以降では、ハッシュ値省略記法により、render 'schedule', pair_work: という形式が有効です。これは render 'schedule', pair_work: pair_work と等価で、同名の変数がスコープ内に存在する場合にのみ使用できます。fjordllc/bootcamp プロジェクトではこのモダンな Ruby 構文が使用されているため、構文エラーとして誤って指摘しないことを推奨します。対象ファイルは Slim テンプレート(例: app/views/.../*.slim)全体に適用可能です。
Applied to files:
app/views/practices/reports/index.html.slim
📚 Learning: 2026-01-09T10:57:42.506Z
Learnt from: CR
Repo: fjordllc/bootcamp PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-09T10:57:42.506Z
Learning: Applies to app/**/*.rb : Place Rails app code in `app/` directory with subdirectories for `models/`, `controllers/`, `views/`, `jobs/`, `helpers/`, and frontend code under `javascript/`
Applied to files:
.rubocop.yml
📚 Learning: 2026-01-09T10:57:42.506Z
Learnt from: CR
Repo: fjordllc/bootcamp PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-09T10:57:42.506Z
Learning: Applies to app/**/*.rb : Follow Rails file naming conventions (e.g., `app/models/user.rb`)
Applied to files:
.rubocop.yml
🧬 Code graph analysis (2)
app/javascript/grant-filter.js (1)
app/javascript/components/Reports.jsx (1)
withGrant(25-25)
app/javascript/components/Reports.jsx (1)
app/javascript/user_mentor_memo.js (1)
userId(9-9)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: build_and_test
🔇 Additional comments (7)
app/controllers/api/reports_controller.rb (1)
11-11: LGTM!
with_grantパラメータによるフィルタリングの実装は適切です。文字列比較== 'true'はクエリパラメータの処理として正しく、既存のフィルタチェーンとの組み合わせも問題ありません。db/fixtures/discord_profiles.yml (1)
339-342: LGTM!
grant-courseユーザーに対応する Discord プロファイルフィクスチャが適切に追加されています。users.ymlの冒頭コメント(「userを増やした場合、以下のymlにも追記する」)に従った正しい対応です。db/fixtures/talks.yml (1)
238-241: LGTM!新しい
talk_grant_courseフィクスチャは既存のパターンに従っており、grant-courseユーザーと正しく関連付けられています。db/fixtures/reports.yml (1)
509-515:practicesの関連付けがない点を確認してください。給付金コースのフィルター機能をテストするためには、このレポートが給付金コースのプラクティス(
source_idを持つプラクティス)に関連付けられている必要がある可能性があります。with_grant_practicesスコープはpractices.source_id IS NOT NULLでフィルタリングするため、プラクティスの関連付けがないとフィルター機能のテストが正しく動作しない可能性があります。app/javascript/grant-filter.js (1)
47-56: LGTM!
destroy()メソッドでのイベントリスナーの削除と状態のクリーンアップは適切に実装されています。メモリリークを防ぐ良い実装です。app/javascript/components/Reports.jsx (1)
72-89: LGTM!grant filter のプレースホルダー要素の条件付きレンダリングは正しく実装されています。空の状態と結果がある状態の両方でフィルターが表示されるようになっています。
app/views/practices/reports/index.html.slim (1)
14-14: LGTM!
practiceSourceId:@practice.source_id`` の追加により、React コンポーネントが給付金コースかどうかを判断できるようになります。source_idが `nil` の場合は通常のプラクティス、値がある場合は給付金コースとして正しく処理されます。
✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.
| render(element) { | ||
| element.innerHTML = ` | ||
| <nav class="pill-nav"> | ||
| <ul class="pill-nav__items"> | ||
| <li class="pill-nav__item"> | ||
| <button class="pill-nav__item-link" data-with-grant="false">全て</button> | ||
| </li> | ||
| <li class="pill-nav__item"> | ||
| <button class="pill-nav__item-link" data-with-grant="true">給付金コース</button> | ||
| </li> | ||
| </ul> | ||
| </nav | ||
| ` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
HTML構文エラー: </nav> の閉じタグが不完全です。
Line 20 で </nav となっており、> が欠落しています。これによりHTMLのパースが正しく行われない可能性があります。
🐛 修正案
element.innerHTML = `
<nav class="pill-nav">
<ul class="pill-nav__items">
<li class="pill-nav__item">
<button class="pill-nav__item-link" data-with-grant="false">全て</button>
</li>
<li class="pill-nav__item">
<button class="pill-nav__item-link" data-with-grant="true">給付金コース</button>
</li>
</ul>
- </nav
+ </nav>
`📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| render(element) { | |
| element.innerHTML = ` | |
| <nav class="pill-nav"> | |
| <ul class="pill-nav__items"> | |
| <li class="pill-nav__item"> | |
| <button class="pill-nav__item-link" data-with-grant="false">全て</button> | |
| </li> | |
| <li class="pill-nav__item"> | |
| <button class="pill-nav__item-link" data-with-grant="true">給付金コース</button> | |
| </li> | |
| </ul> | |
| </nav | |
| ` | |
| render(element) { | |
| element.innerHTML = ` | |
| <nav class="pill-nav"> | |
| <ul class="pill-nav__items"> | |
| <li class="pill-nav__item"> | |
| <button class="pill-nav__item-link" data-with-grant="false">全て</button> | |
| </li> | |
| <li class="pill-nav__item"> | |
| <button class="pill-nav__item-link" data-with-grant="true">給付金コース</button> | |
| </li> | |
| </ul> | |
| </nav> | |
| ` |
🤖 Prompt for AI Agents
In `@app/javascript/grant-filter.js` around lines 9 - 21, The template string in
render(element) contains a malformed closing tag `</nav` (missing the trailing
'>') which breaks HTML parsing; update the template literal in the
render(element) method (in grant-filter.js) to use a proper closing `</nav>` tag
so the generated markup is valid.
| grant-course: | ||
| login_name: grant-course | ||
| email: [email protected] | ||
| crypted_password: $2a$10$n/xv4/1luueN6plzm2OyDezWlZFyGHjQEf4hwAW1r3k.lCm0frPK. # testtest | ||
| salt: zW3kQ9ubsxQQtzzzs4ap | ||
| name: 給付金コースのユーザー | ||
| name_kana: 給付金コースのユーザー | ||
| github_account: grant-course | ||
| twitter_account: grant-course | ||
| facebook_url: https://www.facebook.com/fjordllc/grant-course | ||
| blog_url: http://grant-course.org | ||
| description: "給付金コースを受講中のユーザーです。" | ||
| course: course5 | ||
| job: office_worker | ||
| os: mac | ||
| organization: Rails大学 | ||
| updated_at: "2025-01-01 00:00:00" | ||
| created_at: "2025-01-01 00:00:00" | ||
| last_activity_at: "2025-01-01 00:00:00" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
name_kana の形式について確認してください。
フィクスチャの追加自体は問題ありませんが、name_kana が他のユーザーフィクスチャと異なり、カタカナ形式ではなく漢字のまま設定されています。
name: 給付金コースのユーザー
name_kana: 給付金コースのユーザー # 他のフィクスチャは「キュウフキンコースノユーザー」のようなカタカナ形式テストデータとしては動作に影響しませんが、一貫性のために修正を検討してください。
♻️ 修正案
- name_kana: 給付金コースのユーザー
+ name_kana: キュウフキンコースノユーザー🤖 Prompt for AI Agents
In `@db/fixtures/users.yml` around lines 1559 - 1577, The name_kana field is set
in kanji instead of katakana; update the fixture entry for login_name
grant-course by replacing name_kana: 給付金コースのユーザー with the katakana form (e.g.
name_kana: キュウフキンコースノユーザー) so it matches other user fixtures and maintains
consistency with name: 給付金コースのユーザー.
Issue
概要
給付金コースのプラクティスの関連日報一覧(/practices/:id/reports)に元コースの関連日報の表示/非表示を切り替えるフィルターを追加
lib/tasks/bootcamp.rake変更確認方法
feature/reports-grant-course-filterをローカルに取り込む初期データの用意
給付金コースのプラクティス、給付金コースのユーザの日報を用意します。
grant-courseユーザでログイン動作確認
フィルター表示/非表示
komagataでログインgrant-courseでログインフィルタリング
grant-courseでログイン給付金が日報が0件の時の表示
grant-courseでログインScreenshot
変更前
変更後
Summary by CodeRabbit
リリースノート
新機能
その他
✏️ Tip: You can customize this high-level summary in your review settings.