Skip to content

提出物のテンプレートを作成・編集できるようにする#10045

Open
koguchi-e wants to merge 8 commits into
mainfrom
feature/product-template
Open

提出物のテンプレートを作成・編集できるようにする#10045
koguchi-e wants to merge 8 commits into
mainfrom
feature/product-template

Conversation

@koguchi-e

@koguchi-e koguchi-e commented May 20, 2026

Copy link
Copy Markdown
Contributor

Issue

概要

受講生が提出物の形式を間違えてしまうのを防ぐよう、提出物のテンプレートを作成しました。

メンターのみ、プラクティスごとに提出物のテンプレートを作成・編集ができます。
テンプレートを設定すると、提出物作成ページで設定した文字がtextareaに入力されます。

変更確認方法

テンプレートを新規に作成

  1. feature/product-templateをローカルに取り込む
  2. 開発サーバーを起動
  3. http://localhost:3000/ にアクセスし、mentormentaro 等メンターでログイン
  4. メンターページのプラクティス画面」から任意のプラクティス編集画面を開く
  5. 「提出物のテンプレート」欄に文字列をを入力して更新する
  6. 更新後、該当プラクティス詳細画面から「提出物を作る」をクリックする
  7. 提出物作成画面の入力欄にテンプレートが反映されていることを確認する

テンプレートの未設定時の動作確認

  1. 「テンプレートを新規に作成」の4の手順まで行う
  2. 提出物テンプレートを入力せずプラクティスを更新する
  3. 「提出物を作る」をクリックする
  4. 提出物入力欄が空で表示されることを確認する

Screenshot

変更前

スクリーンショット 2026-05-22 172859

変更後

スクリーンショット 2026-07-07 113634 スクリーンショット 2026-07-07 113656

Flakewatch Report

Flakewatch Report

Summary by CodeRabbit

  • 新機能
    • プラクティスにプロダクトテンプレートを追加。メンターは作成・編集画面でテンプレート説明を作成・更新・削除可能。
    • プロダクト作成フォームでテンプレート説明が本文の初期値として自動反映されるように。
    • フォームにテンプレート説明入力欄とリアルタイムプレビューを追加。
  • テスト
    • プラクティス/プロダクトのテンプレート機能に関するシステムテストを追加・更新。

Review App

@koguchi-e koguchi-e self-assigned this May 20, 2026
@coderabbitai

coderabbitai Bot commented May 20, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Practice に紐づく ProductTemplate モデルとマイグレーションを追加し、Practice 側に has_one と accepts_nested_attributes_for を設定。コントローラでフォーム用の初期化と許可パラメータを追加し、フォーム/商品画面/システムテストを更新しています。

Changes

プロダクトテンプレート機能実装

Layer / File(s) Summary
ProductTemplateモデルとデータベーススキーマ
app/models/product_template.rb, db/migrate/20260520061059_create_product_templates.rb, db/schema.rb
ProductTemplate を新規追加し、belongs_to :practicedescription/practice の presence バリデーションを設定。マイグレーションで product_templates テーブルを作成し schema に反映。
Practiceモデルの関連性と属性受け入れ
app/models/practice.rb
has_one :product_template, dependent: :destroy を追加し、`accepts_nested_attributes_for :product_template, update_only: true, allow_destroy: true, reject_if: proc {
コントローラの初期化とパラメータ処理
app/controllers/mentor/practices_controller.rb
new で常に @practice.build_product_template を呼び、edit では未存在時のみ build。practice_paramsproduct_template_attributes: %i[id description _destroy] を追加。
プラクティスフォームのテンプレート入力欄
app/views/mentor/practices/_form.html.slim
f.fields_for :product_template を追加し、description 用テキストエリアと .js-product-template-preview を追加。
商品フォームへのテンプレート本文デフォルト値適用
app/views/products/_form.html.slim
@product.practice.product_template&.description をテンプレートとして読み、`@product.body.presence
システムテストとテスト用フィクスチャ
test/fixtures/product_templates.yml, test/system/practices/mentor_test.rb
フィクスチャを追加し、プラクティス作成・更新テストにテンプレート説明フィールドの入力と、空時・反映時の検証アサーションを追加。
sequenceDiagram
  participant Mentor as Mentor
  participant Controller as Mentor::PracticesController
  participant Practice as Practice
  participant Template as ProductTemplate
  participant DB as Database

  Mentor->>Controller: プラクティス作成/編集ページへアクセス
  Controller->>Practice: build_product_template (new) / fetch product_template (edit)
  Controller->>Mentor: フォーム(fields_for: product_template.description)を表示
  Mentor->>Controller: フォーム送信 (product_template_attributes 含む)
  Controller->>Practice: accepts_nested_attributes_for 経由で product_template を作成/更新/削除
  Practice->>DB: product_templates テーブルへ INSERT/UPDATE/DELETE
  Controller->>Mentor: リダイレクト/レスポンス
Loading

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related issues

Suggested reviewers

  • okuramasafumi

🐰 テンプレート描くウサギ
ことばを集めて綴るよ
フォームの隅にそっと置き
空の本文に寄り添えば
投稿は今日も輝く ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed 提出物テンプレートの作成・編集機能追加という主変更を端的に表しており、変更内容と一致しています。
Description check ✅ Passed Issue、概要、変更確認方法、Screenshotの各項目が揃っており、テンプレートに概ね沿った内容です。
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/product-template

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.

@github-actions

github-actions Bot commented May 20, 2026

Copy link
Copy Markdown

🚀 Review App

URL: https://bootcamp-pr-10045-fvlfu45apq-an.a.run.app

Basic認証: fjord / (ステージングと同じ)
PR更新時に自動で再デプロイされます。

@koguchi-e koguchi-e force-pushed the feature/product-template branch 3 times, most recently from fb2a06d to ee3e9a5 Compare May 22, 2026 07:57
@koguchi-e koguchi-e marked this pull request as ready for review May 22, 2026 08:45
@github-actions github-actions Bot requested a review from okuramasafumi May 22, 2026 08:45

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (4)
app/models/product_template.rb (1)

7-7: ⚡ Quick win

validates :practice は冗長です。

Rails 5以降では belongs_to 関連が自動的に存在を検証するため、line 7 の validates :practice, presence: true は不要です。

♻️ 提案する修正
 class ProductTemplate < ApplicationRecord
   belongs_to :practice
 
   validates :description, presence: true
-  validates :practice, presence: true
 end
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/models/product_template.rb` at line 7, Remove the redundant explicit
presence validation for the practice association in ProductTemplate: delete the
line validating :practice (the validates :practice, presence: true) since the
belongs_to :practice association already enforces presence in Rails 5+; leave
the belongs_to :practice declaration intact and run model specs to confirm
behavior.
app/models/practice.rb (1)

30-30: 💤 Low value

reject_if ブロック内のキーはシンボルを使用することを検討してください。

attributes['description'] は文字列キーを使用していますが、Railsの慣習では attributes[:description] のようにシンボルキーを使う方が一般的です。ただし、ネストされた属性では文字列とシンボル両方が渡される可能性があるため、安全のために attributes['description'].blank? && attributes[:description].blank? または attributes.dig('description').blank? && attributes.dig(:description).blank? とするか、現状のまま文字列キーのみで十分な場合もあります。

💡 参考: より安全な実装例
accepts_nested_attributes_for :product_template, 
  update_only: true, 
  allow_destroy: true, 
  reject_if: proc { |attributes| 
    attributes['description'].blank? && attributes[:description].blank?
  }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/models/practice.rb` at line 30, reject_if block for
accepts_nested_attributes_for :product_template uses attributes['description']
(string key) which may miss symbol keys; update the proc used in the
accepts_nested_attributes_for call (the reject_if proc for :product_template) to
check both string and symbol keys (e.g., ensure you test
attributes['description'].blank? && attributes[:description].blank? or use
attributes.dig('description').blank? && attributes.dig(:description).blank?) so
the blank check is robust for either key form.
db/migrate/20260520061059_create_product_templates.rb (1)

5-5: ⚡ Quick win

description カラムに null: false 制約を追加することを検討してください。

モデルで validates :description, presence: true を定義しているため、データベースレベルでも null: false 制約を追加することでデータ整合性をより強固にできます。

🔧 提案する修正
 create_table :product_templates do |t|
   t.references :practice, null: false, foreign_key: true
-  t.text :description
+  t.text :description, null: false
 
   t.timestamps
 end
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@db/migrate/20260520061059_create_product_templates.rb` at line 5, マイグレーション
CreateProductTemplates の description カラムに null: false 制約を追加してください — 現在の行 t.text
:description を null: false に変更し、既存レコードに NULL
が残っている可能性がある場合はマイグレーション内で事前にデフォルト値を入れるかバックフィル(例:
update_all)してから制約を追加する処理を入れてください(マイグレーション名/クラス: CreateProductTemplates、カラム名:
description を参照)。
test/system/practices/mentor_test.rb (1)

30-42: ⚡ Quick win

テンプレート未設定時の検証を追加することを検討してください

このテストはテンプレートなしでプラクティスを作成できることを確認していますが、さらに作成後に new_product_path(practice_id: ...) へ遷移して product[body] フィールドが空であることを検証すると、テンプレート未設定時の動作がより明確になります。

検証の追加例
     assert_text 'プラクティスを作成しました'
+
+    practice = Practice.find_by(title: 'テンプレなし')
+    visit new_product_path(practice_id: practice.id)
+    assert_field 'product[body]', with: ''
   end
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/system/practices/mentor_test.rb` around lines 30 - 42, Extend the test
'can create practice without product template' to after asserting
'プラクティスを作成しました' follow the redirect to the product creation page for the new
practice (the equivalent of new_product_path(practice_id: ...)), locate the
product form (e.g. form[name=product]) and assert that the 'product[body]' field
is blank so the behavior with no product template is explicitly verified; use
the created practice's id from the page or by querying Practice.last to build
the product path and then assert_field 'product[body]', with: '' (or
assert_equal '' on its value).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@app/controllers/mentor/practices_controller.rb`:
- Around line 67-68:
ストロングパラメータでネストされたテンプレート削除が無効になっているので、practice_params(または該当の強いパラメータメソッド)内の
product_template_attributes に :_destroy を追加してください(現在
product_template_attributes: %i[id description] を product_template_attributes:
%i[id description _destroy] のように変更)。モデル側で allow_destroy: true を使っている
product_template のネストされた属性が正しく削除されるようにすること。

---

Nitpick comments:
In `@app/models/practice.rb`:
- Line 30: reject_if block for accepts_nested_attributes_for :product_template
uses attributes['description'] (string key) which may miss symbol keys; update
the proc used in the accepts_nested_attributes_for call (the reject_if proc for
:product_template) to check both string and symbol keys (e.g., ensure you test
attributes['description'].blank? && attributes[:description].blank? or use
attributes.dig('description').blank? && attributes.dig(:description).blank?) so
the blank check is robust for either key form.

In `@app/models/product_template.rb`:
- Line 7: Remove the redundant explicit presence validation for the practice
association in ProductTemplate: delete the line validating :practice (the
validates :practice, presence: true) since the belongs_to :practice association
already enforces presence in Rails 5+; leave the belongs_to :practice
declaration intact and run model specs to confirm behavior.

In `@db/migrate/20260520061059_create_product_templates.rb`:
- Line 5: マイグレーション CreateProductTemplates の description カラムに null: false
制約を追加してください — 現在の行 t.text :description を null: false に変更し、既存レコードに NULL
が残っている可能性がある場合はマイグレーション内で事前にデフォルト値を入れるかバックフィル(例:
update_all)してから制約を追加する処理を入れてください(マイグレーション名/クラス: CreateProductTemplates、カラム名:
description を参照)。

In `@test/system/practices/mentor_test.rb`:
- Around line 30-42: Extend the test 'can create practice without product
template' to after asserting 'プラクティスを作成しました' follow the redirect to the product
creation page for the new practice (the equivalent of
new_product_path(practice_id: ...)), locate the product form (e.g.
form[name=product]) and assert that the 'product[body]' field is blank so the
behavior with no product template is explicitly verified; use the created
practice's id from the page or by querying Practice.last to build the product
path and then assert_field 'product[body]', with: '' (or assert_equal '' on its
value).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 2a1c943f-f00c-4fd6-b011-61c37ecf6593

📥 Commits

Reviewing files that changed from the base of the PR and between 39bd80f and 57dabdf.

📒 Files selected for processing (9)
  • app/controllers/mentor/practices_controller.rb
  • app/models/practice.rb
  • app/models/product_template.rb
  • app/views/mentor/practices/_form.html.slim
  • app/views/products/_form.html.slim
  • db/migrate/20260520061059_create_product_templates.rb
  • db/schema.rb
  • test/fixtures/product_templates.yml
  • test/system/practices/mentor_test.rb

Comment thread app/controllers/mentor/practices_controller.rb Outdated
@koguchi-e koguchi-e force-pushed the feature/product-template branch from 57dabdf to c59279d Compare May 26, 2026 01:33

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
test/system/practices/mentor_test.rb (1)

43-43: ⚡ Quick win

Practice.last 依存を避けてテストを安定化してください。

Practice.last.id は他データの影響を受けやすいので、作成時に使った属性(例: title)で対象を特定する方が安全です。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/system/practices/mentor_test.rb` at line 43, Replace the fragile
Practice.last.id usage by locating the specific Practice you created in the test
(or capturing the created record) and using its id; e.g. use the Practice
instance returned by your factory (the variable assigned from create(:practice,
title: "...")) or do Practice.find_by(title: "the test title").id instead of
Practice.last.id so the test targets the exact record reliably.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@app/models/practice.rb`:
- Around line 29-30: Add a DB-level uniqueness constraint for the has_one
association by creating a migration that adds a UNIQUE INDEX on
product_templates.practice_id (and handle nullable behavior if applicable), and
if existing duplicates may exist write a data migration/cleanup step to remove
or consolidate duplicate product_template rows before adding the index; update
the Practice model (has_one :product_template) only if any validations/foreign
key options need adjustment but ensure product_templates.practice_id is
constrained uniquely at the database level to enforce the has_one invariant.

In `@app/views/products/_form.html.slim`:
- Line 12: The assignment to template uses `@product.practice` without guarding
against nil, so change the expression that sets template (the line with template
= `@product.practice.product_template`&.description) to safely navigate practice
as well (use safe navigation on `@product.practice` before calling
product_template) so it won't raise when `@product.practice` is nil; keep the
existing safe navigation on product_template and description.

---

Nitpick comments:
In `@test/system/practices/mentor_test.rb`:
- Line 43: Replace the fragile Practice.last.id usage by locating the specific
Practice you created in the test (or capturing the created record) and using its
id; e.g. use the Practice instance returned by your factory (the variable
assigned from create(:practice, title: "...")) or do Practice.find_by(title:
"the test title").id instead of Practice.last.id so the test targets the exact
record reliably.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: b6c263c7-d89c-418e-ace1-6590d16bfdc9

📥 Commits

Reviewing files that changed from the base of the PR and between 57dabdf and c59279d.

📒 Files selected for processing (9)
  • app/controllers/mentor/practices_controller.rb
  • app/models/practice.rb
  • app/models/product_template.rb
  • app/views/mentor/practices/_form.html.slim
  • app/views/products/_form.html.slim
  • db/migrate/20260520061059_create_product_templates.rb
  • db/schema.rb
  • test/fixtures/product_templates.yml
  • test/system/practices/mentor_test.rb
✅ Files skipped from review due to trivial changes (3)
  • db/migrate/20260520061059_create_product_templates.rb
  • test/fixtures/product_templates.yml
  • db/schema.rb

Comment thread app/models/practice.rb Outdated
Comment thread app/views/products/_form.html.slim
@koguchi-e koguchi-e force-pushed the feature/product-template branch 2 times, most recently from 9449be6 to b8e233a Compare May 26, 2026 02:28

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@db/migrate/20260520061059_create_product_templates.rb`:
- Line 10: The migration currently creates an automatic index for the
practice_id via t.references :practice and then adds another add_index
:product_templates, :practice_id, unique: true which can conflict; fix by
removing the separate add_index line and instead declare the unique index on the
reference itself (change t.references :practice to t.references :practice,
index: { unique: true }) so only one uniquely-named index
(index_product_templates_on_practice_id) is created.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: d9ffc97b-12d5-43ea-b062-8677bd5487a5

📥 Commits

Reviewing files that changed from the base of the PR and between 9449be6 and b8e233a.

📒 Files selected for processing (4)
  • app/controllers/mentor/practices_controller.rb
  • app/models/product_template.rb
  • db/migrate/20260520061059_create_product_templates.rb
  • test/system/practices/mentor_test.rb
💤 Files with no reviewable changes (1)
  • app/models/product_template.rb

Comment thread db/migrate/20260520061059_create_product_templates.rb Outdated
@koguchi-e koguchi-e force-pushed the feature/product-template branch from b8e233a to 3543386 Compare May 26, 2026 02:53
@koguchi-e koguchi-e requested a review from djkazunoko May 26, 2026 04:35
@koguchi-e

Copy link
Copy Markdown
Contributor Author

@djkazunoko
お疲れ様です。

Fjord Choice にPRがございましたが、該当のPRがcloseになっておりましたため、レビュー依頼を送らせていただきました。

すでに他レビューを依頼されているなど、
何かございましたらお気軽にご連絡ください~!
どうぞよろしくお願いいたします🙏

@djkazunoko

Copy link
Copy Markdown
Contributor

@koguchi-e
お疲れ様です!
来週中に確認いたします!

@komagata komagata force-pushed the main branch 2 times, most recently from b420541 to f31c31e Compare June 4, 2026 07:05
@djkazunoko

Copy link
Copy Markdown
Contributor

@koguchi-e
PRの差分を確認したところ、他のブランチの変更も含まれているように見えました。
意図した差分のみになっているか再度ご確認いただけますでしょうか?

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@app/models/practice.rb`:
- Line 30: The current reject_if proc on accepts_nested_attributes_for
:product_template blocks changes like clearing or destroying existing templates;
change the predicate so it only rejects truly empty new records — i.e., only
reject when the record has no id (new record) AND description is blank AND
_destroy is not set — so updates or _destroy operations on existing
product_template are not ignored; update the reject_if proc on
accepts_nested_attributes_for :product_template accordingly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: bf0a77ca-ae41-4c50-af5b-65d73369613c

📥 Commits

Reviewing files that changed from the base of the PR and between b8e233a and 7fa8cb7.

📒 Files selected for processing (9)
  • app/controllers/mentor/practices_controller.rb
  • app/models/practice.rb
  • app/models/product_template.rb
  • app/views/mentor/practices/_form.html.slim
  • app/views/products/_form.html.slim
  • db/migrate/20260520061059_create_product_templates.rb
  • db/schema.rb
  • test/fixtures/product_templates.yml
  • test/system/practices/mentor_test.rb
✅ Files skipped from review due to trivial changes (1)
  • app/models/product_template.rb
🚧 Files skipped from review as they are similar to previous changes (7)
  • test/fixtures/product_templates.yml
  • app/controllers/mentor/practices_controller.rb
  • app/views/mentor/practices/_form.html.slim
  • db/schema.rb
  • db/migrate/20260520061059_create_product_templates.rb
  • test/system/practices/mentor_test.rb
  • app/views/products/_form.html.slim

Comment thread app/models/practice.rb Outdated
@koguchi-e

Copy link
Copy Markdown
Contributor Author

@djkazunoko
ご確認いただきありがとうございます!
こちら再度修正いたしましたので、お手数ですが、再度ご確認いただけますでしょうか?

@djkazunoko

Copy link
Copy Markdown
Contributor

@koguchi-e
確認遅くなり申し訳ございません🙏
コンフリクトの解消をお願いします。

@koguchi-e koguchi-e force-pushed the feature/product-template branch from 7fa8cb7 to dfb9e7b Compare July 2, 2026 01:31
@koguchi-e

Copy link
Copy Markdown
Contributor Author

@djkazunoko
お忙しい中ご確認ありがとうございます!
また、コンフリクトの件失礼いたしました。
こちら修正いたしましたので、お手数ですが再度ご確認をお願いいたします。

@koguchi-e koguchi-e force-pushed the feature/product-template branch from dfb9e7b to 1a71ae5 Compare July 2, 2026 01:57

@djkazunoko djkazunoko left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@koguchi-e
基本的な機能は問題なく動作していることを確認できました!

いくつかコメントしましたので、ご確認お願いします!

Comment thread db/schema.rb Outdated
t.text "description"
t.bigint "practice_id", null: false
t.datetime "updated_at", null: false
t.index ["practice_id"], name: "index_product_templates_on_practice_id"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

unique: trueが消えてしまっているように見えます。
マイグレーションファイルにはindex: { unique: true }の記述があるので、本来ならt.index ["practice_id"], name: "index_product_templates_on_practice_id", unique: trueのようになると思います。

@koguchi-e koguchi-e Jul 6, 2026

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.

ご確認ありがとうございます。
こちら168157bにて修正いたしました。

Comment thread db/schema.rb Outdated

create_table "product_templates", force: :cascade do |t|
t.datetime "created_at", null: false
t.text "description"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

app/models/product_template.rbvalidates :description, presence: trueがあるので、DB側でもt.text :description, null: falseにしておくと、より安全かと思います。

@koguchi-e koguchi-e Jul 6, 2026

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.

こちらも168157bにて修正いたしました。

Comment thread app/models/practice.rb Outdated
has_many :products, dependent: :destroy

has_one :product_template, dependent: :destroy
accepts_nested_attributes_for :product_template, update_only: true, allow_destroy: true, reject_if: proc { |attributes| attributes['description'].blank? }

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

allow_destroy: true が設定されていますが、フォーム上ではテンプレートを削除する操作が見当たりませんでした。

reject_ifにより、既存のテンプレートを空にして更新しても更新自体がスキップされるため、テンプレートを削除できないように見えました。

テンプレートを削除できるようにするかどうかは仕様にも関わる部分だと思うので、@komagataさん @machidaさんに確認した方がよいように思いました。

個人的には、一度設定したテンプレートを不要にしたいケースもあると思うので、テンプレートを削除できる動線があった方が良いのではないかと感じました。

@koguchi-e koguchi-e Jul 6, 2026

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.

@djkazunoko
こちらご指摘ありがとうございます。
見逃しておりました、大変助かります。

@komagata @machida
こちらの件について、テンプレートを削除できるようにする必要はありますでしょうか?

削除できるようにする場合は、フォームに削除用のチェックボックスを追加し、チェックした状態で更新するとテンプレートが削除される形で実装しようと考えています。

削除が不要の場合は、allow_destroy: true を削除する予定です。

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.

@koguchi-e 空にできるようにしたいです〜

@koguchi-e koguchi-e Jul 7, 2026

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
ご回答ありがとうございました。こちら承知しました。

@djkazunoko
こちら47bd2a7にて削除機能を追加いたしました。
以下のように、テンプレートがある場合、削除用のチェックボックスが表示され
チェックした状態で更新すると、テンプレートが削除されるようにしています。

スクリーンショット 2026-07-07 113123

また、削除機能のシステムテストを追加しました。
加えて、提出物テンプレート機能に関するモデルテストが不足していたため、あわせて追加しております。

@koguchi-e koguchi-e force-pushed the feature/product-template branch 5 times, most recently from d11c672 to 4cdd755 Compare July 7, 2026 02:50
@koguchi-e koguchi-e force-pushed the feature/product-template branch from 4cdd755 to 47bd2a7 Compare July 13, 2026 02:12
@djkazunoko

Copy link
Copy Markdown
Contributor

@koguchi-e
今回の要件だとproduct_templatesテーブルを作らずに、practicesテーブルに提出物テンプレート用のカラムを追加する構成でも実現できそうかなと思いました。別テーブルにしたことで少し複雑になっているように思います。

@koguchi-e

Copy link
Copy Markdown
Contributor Author

@djkazunoko
ご指摘ありがとうございます!

確かに、今回の要件だけであれば、practicesテーブルにカラムを追加する方が実装をシンプルにできると考えています。

一方で、今回は以下の2点を重視し、提出物テンプレートを別モデル・別テーブルとして実装しました。

1. 既存の日報テンプレート機能との一貫性

既存の日報テンプレート機能が、テンプレートを独立したモデルとして扱う構成になっていたため、今回の提出物テンプレート機能についても同様の構成にしました。

実装方針をそろえることで、コードを読む際の理解や今後の保守をしやすくしたいと考えました。

2. 責務の分離

提出物テンプレートは、Practiceそのものの属性ではなく、Practiceに付随する独立した情報として扱いたいと考えました。

別モデルにすることで、今後テンプレート固有の属性やバリデーションが追加された場合にも、それらをPracticeモデルへ持たせず、テンプレート側の責務として管理できます。

また、Practiceモデルには現時点で# rubocop:todo Metrics/ClassLengthが設定されており、すでに多くの関連や処理を持っている状態です。
こちらは将来的には解消する方針と伺ってます。#10022 (comment)

提出物テンプレートのカラム追加ですぐにモデルが大きくなってしまうわけはありませんが、今後提出物テンプレートに新たな処理が追加された際もそれらの責務もPracticeモデルに持たせることは避けたいと考え、別モデルとして分離する設計にしました。

ご指定の通り、実装は複雑になってしまっているのですが、
既存の実装と一貫性を持たせて分かりやすくすることと
責務を分離させることを優先させ、このような実装にしております。

@djkazunoko

Copy link
Copy Markdown
Contributor

@koguchi-e
ご説明ありがとうございます!
設計の意図は理解できました。その上で自分の考えも共有させていただきます。


既存の日報テンプレート機能との一貫性についてですが、日報テンプレートはユーザーに紐づく情報である一方、今回の提出物テンプレートはプラクティスに紐づく情報なので、事情は少し異なるのかなと感じました。

提出物テンプレートは「このプラクティスではこのテンプレートを使う」というプラクティス固有の情報だと思うので、Practiceが持つ属性として扱っても自然なのではないかと感じました。

Practiceに提出物テンプレート用の属性を持たせる構成であれば、今回の要件もよりシンプルに実現できそうかなと思います。

また「今後テンプレート固有の属性やバリデーションが増える可能性」については、その時点で切り出す判断でもよいのではないかと思っています。(YAGNIの考え方に近いイメージです。)

既存実装との一貫性や将来の拡張性を重視する考え方も理解できますので、このあたりは設計方針に関わる部分だと思います。
どちらの構成が望ましいかは自分だけでは判断がつかないので、@komagataさん @machidaさん の見解も伺ってみたいです。

@machida

machida commented Jul 14, 2026

Copy link
Copy Markdown
Member

@koguchi-e @djkazunoko

メンションありがとうございます!
実装の観点を把握しました👍
僕はkazunokoさんの考えでいました。

ただ、この後に提出物によってプロンプトを分けるというIssueも控えています。
また、将来的に提出物毎にバリデーションもかけられるといいなとも思っています。

それを踏まえてどちらがいいかを @komagata さんに判断してもらいたいと思いますー

@komagata こちらの判断をお願いします

@komagata

komagata commented Jul 14, 2026

Copy link
Copy Markdown
Member

@koguchi-e @djkazunoko @machida

わかりやすくするために箇条書きで書かせていただきました〜

komagataの意見

  • 提出物のテンプレートをポリモーフィック関連(templateテーブル)として実装する。
  • 既存のreport_templateを(別issueで)report_presetにリネームする。(今後を見据えてポリモーフィック関連でもいいが、ユーザー側ではそんなに対象がないかも)

気にしている観点

  • user, report, productなどmodelがでかすぎるのでカラム追加は辞めたい。(user -> discord_profileなどカラムから別モデルへのリファクタリングをプロジェクト全体で進めている)
  • 管理側からのテンプレート機能は増えていく予定なのでその前提で作りたい。
  • 既存のreport_templateは別概念だが同じtemplateという名前を使っているのが紛らわしすぎる。

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.

4 participants