Skip to content

ブックマーク編集・削除機能を追加#4

Open
goofmint wants to merge 3 commits into
mainfrom
issue-3-edit-delete-bookmarks
Open

ブックマーク編集・削除機能を追加#4
goofmint wants to merge 3 commits into
mainfrom
issue-3-edit-delete-bookmarks

Conversation

@goofmint
Copy link
Copy Markdown
Owner

@goofmint goofmint commented May 29, 2026

概要

fixes #3

  • ブックマークのタイトル、メモ、タグを編集できる画面を追加
  • 一覧カード右上に編集・削除アクションを追加
  • 削除前の確認ダイアログと物理削除を実装
  • 編集・削除のコントローラテストを追加

テスト

  • ./gradlew test

Summary by CodeRabbit

新機能

  • ブックマーク編集・削除機能を追加しました
  • 編集画面でタイトル、メモ、タグの修正が可能になります
  • ブックマークカードに編集・削除ボタンを追加

スタイル

  • ブックマークカード内に説明とタグを表示
  • 操作ボタンのスタイルと配置を改善

テスト

  • CRUD機能の包括的なテストを新規追加

Review Change Stack

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 29, 2026

📝 Walkthrough

Walkthrough

このPRはブックマークアプリの編集・削除機能を実装します。リポジトリにfindById/update/deleteメソッドを追加し、コントローラで対応するエンドポイントと入力正規化・バリデーションロジックを実装。Thymeleafテンプレートと新規スタイルで編集フォームと操作UIを構築し、MockMvcテストでCRUD操作を包括的に検証します。

Changes

ブックマーク編集・削除機能実装

Layer / File(s) Summary
リポジトリのデータアクセス層
src/main/java/com/example/bookmark/BookmarkRepository.java
RowMapperを導入してクエリ結果をBookmarkに変換。findById(id)でOptionalを返す単一取得、update(id,title,description,tags)と delete(id)で影響行数から真偽を返す。
コントローラのエンドポイントと入力正規化
src/main/java/com/example/bookmark/BookmarkController.java
GET /bookmarks/{id}/editで編集画面を表示、POST /bookmarks/{id}で正規化・バリデーション・更新を実行、POST /bookmarks/{id}/deleteで削除を実行。タイトル100文字以下・必須、説明300文字以下の検証とタグのカンマ分割・トリム・空要素除去を実装。
Thymeleafテンプレートと操作UI
src/main/resources/templates/edit.html, src/main/resources/templates/index.html
編集画面テンプレートを新規追加。インデックスページに編集リンク・削除フォーム(確認ダイアログ付き)を追加、説明とタグをカード内に表示。
スタイリング
src/main/resources/static/styles.css
セクション見出しの折り返し制御・フォームグリッド、操作ボタンの統一スタイル・ホバー動作、ブックマークカードの相対配置・右上への絶対配置、説明のpre-wrap・タグのピル状表示、レスポンシブ調整を実装。
エンドツーエンドのテスト検証
src/test/java/com/example/bookmark/BookmarkControllerTest.java
MockMvcとJdbcTemplateでCRUD入出力とDB反映を検証。編集画面・更新・バリデーション・削除の各ケースを独立したテストで網羅。
設定・メタデータ更新
.coderabbit.yaml, .gitignore
CodeRabbitレビューガイダンスのJava向けに入力検証のサーバー側確認文言を追加。テンプレート・SQLスキーマ・ドキュメント向けブロックの定型文を削除。.DS_Storeをgitignoreに追加。

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • goofmint/bookmark-app-java#1: 初期のBookmarkController/BookmarkRepositoryを基盤とする参照実装で、このPRが編集・更新・削除エンドポイント・リポジトリメソッド・テストを拡張するもの。

Poem

🐰 ブックマーク編集・削除、いざ実装!
コントローラー正規化、リポジトリ更新・削除
テンプレートにボタン並べて、スタイルで飾る
入力検証は厳格に、サーバー側も確認して
MockMvcテスト網羅し、機能完成🎉

🚥 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
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed PR タイトル「ブックマーク編集・削除機能を追加」は、変更セットの主な内容(ブックマーク編集・削除機能の実装)を明確に要約しており、チームメンバーがコミット履歴をスキャンする際に主要な変更を理解できます。
Linked Issues check ✅ Passed PR は Issue #3 の全ての要件を実装しています。編集画面(edit.html)を追加し、タイトル・メモ・タグの編集機能を実装し、削除機能を物理削除で実装し、削除前に確認ダイアログを表示し、編集・削除操作は絵文字で右上に表示しており、入力検証(タイトル必須・100文字以下、メモ300文字以下)とタグのカンマ区切り表示も実装されています。
Out of Scope Changes check ✅ Passed PR に含まれる変更は全て Issue #3 の要件の実装に直接関連しています。.coderabbit.yaml と .gitignore の変更は設定ファイルの調整で、styles.css の変更は編集画面と操作 UI のスタイル実装に必要です。

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ 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 issue-3-edit-delete-bookmarks

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

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: 2

🤖 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 `@src/main/java/com/example/bookmark/BookmarkController.java`:
- Around line 92-95: Current code checks existence with
bookmarkRepository.findById(id) before calling update/delete, which can race
with concurrent requests; instead call the update(...) method and use its return
value (or affected-row count) to determine success and set
redirectAttributes.addFlashAttribute("error", ...) when update(...) indicates
failure; remove reliance on the prior existence check (or keep it only for early
fast-fail) but always treat update(...)'s boolean/rows-updated as the final
authority for both the update(...) call(s) and the similar case around the lines
107-108, returning "redirect:/" with an error flash when the update indicates no
rows were changed.

In `@src/test/java/com/example/bookmark/BookmarkControllerTest.java`:
- Line 20: テストで使っている固定パス "/private/tmp/..." を OS 依存にしないため、BookmarkControllerTest
の `@SpringBootTest`(properties = "...") に設定している spring.datasource.url を相対パス(例:
"./build/tmp/bookmark-controller-test.db")か System.getProperty("java.io.tmpdir")
を使った一意のパスに置き換えてください; 具体的には BookmarkControllerTest クラスの `@SpringBootTest`
アノテーション内プロパティ文字列を動的に組み立てるか、テスト用のプロパティプロバイダ(環境変数・@TestPropertySource など)を使って
java.io.tmpdir ベースのパスを設定し、CI や他OSでも同じように動作するようにしてください.
🪄 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: e0c9c868-a936-42bb-90a5-c6019124096f

📥 Commits

Reviewing files that changed from the base of the PR and between 700e006 and a0f5c43.

📒 Files selected for processing (8)
  • .coderabbit.yaml
  • .gitignore
  • src/main/java/com/example/bookmark/BookmarkController.java
  • src/main/java/com/example/bookmark/BookmarkRepository.java
  • src/main/resources/static/styles.css
  • src/main/resources/templates/edit.html
  • src/main/resources/templates/index.html
  • src/test/java/com/example/bookmark/BookmarkControllerTest.java

Comment on lines +92 to +95
if (bookmarkRepository.findById(id).isEmpty()) {
redirectAttributes.addFlashAttribute("error", "ブックマークが見つかりません。");
return "redirect:/";
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

更新結果を最終判定に使ってください。

存在確認後に別リクエストで削除されると、更新失敗でも成功扱いになります。update(...) の戻り値で判定してエラーを返すようにしてください。

💡 修正案
-        if (bookmarkRepository.findById(id).isEmpty()) {
-            redirectAttributes.addFlashAttribute("error", "ブックマークが見つかりません。");
-            return "redirect:/";
-        }
-
         BookmarkForm form = normalize(title, description, tags);
         String validationError = validate(form);
         if (validationError != null) {
             redirectAttributes.addFlashAttribute("error", validationError);
             redirectAttributes.addFlashAttribute("title", title);
             redirectAttributes.addFlashAttribute("description", description);
             redirectAttributes.addFlashAttribute("tags", tags);
             return "redirect:/bookmarks/" + id + "/edit";
         }
 
-        bookmarkRepository.update(id, form.title(), form.description(), form.tags());
+        if (!bookmarkRepository.update(id, form.title(), form.description(), form.tags())) {
+            redirectAttributes.addFlashAttribute("error", "ブックマークが見つかりません。");
+        }
         return "redirect:/";

Also applies to: 107-108

🤖 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 `@src/main/java/com/example/bookmark/BookmarkController.java` around lines 92 -
95, Current code checks existence with bookmarkRepository.findById(id) before
calling update/delete, which can race with concurrent requests; instead call the
update(...) method and use its return value (or affected-row count) to determine
success and set redirectAttributes.addFlashAttribute("error", ...) when
update(...) indicates failure; remove reliance on the prior existence check (or
keep it only for early fast-fail) but always treat update(...)'s
boolean/rows-updated as the final authority for both the update(...) call(s) and
the similar case around the lines 107-108, returning "redirect:/" with an error
flash when the update indicates no rows were changed.

import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.test.web.servlet.MockMvc;

@SpringBootTest(properties = "spring.datasource.url=jdbc:sqlite:/private/tmp/bookmark-controller-test.db")
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

テストDBパスをOS非依存にしてください。

/private/tmp 固定は実行環境依存で、CI/他OSで失敗しやすいです。相対パス(例: ./build/...)か java.io.tmpdir ベースに変更してください。

💡 修正案
-@SpringBootTest(properties = "spring.datasource.url=jdbc:sqlite:/private/tmp/bookmark-controller-test.db")
+@SpringBootTest(properties = "spring.datasource.url=jdbc:sqlite:./build/bookmark-controller-test.db")
📝 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.

Suggested change
@SpringBootTest(properties = "spring.datasource.url=jdbc:sqlite:/private/tmp/bookmark-controller-test.db")
`@SpringBootTest`(properties = "spring.datasource.url=jdbc:sqlite:./build/bookmark-controller-test.db")
🤖 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 `@src/test/java/com/example/bookmark/BookmarkControllerTest.java` at line 20,
テストで使っている固定パス "/private/tmp/..." を OS 依存にしないため、BookmarkControllerTest の
`@SpringBootTest`(properties = "...") に設定している spring.datasource.url を相対パス(例:
"./build/tmp/bookmark-controller-test.db")か System.getProperty("java.io.tmpdir")
を使った一意のパスに置き換えてください; 具体的には BookmarkControllerTest クラスの `@SpringBootTest`
アノテーション内プロパティ文字列を動的に組み立てるか、テスト用のプロパティプロバイダ(環境変数・@TestPropertySource など)を使って
java.io.tmpdir ベースのパスを設定し、CI や他OSでも同じように動作するようにしてください.

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.

ブックマーク編集、削除機能の実装

1 participant