← 前へ: Phase 5.5 | 目次 | 次へ: Phase 5.7 →
Phase 5.1のSQLインジェクション対策は、このフェーズでも必須です。INSERT・UPDATEの属性値とUPDATE・DELETEのIDをバインドし、動的な属性名は許可リストで制限します。引用符やSQL断片を含む入力を使い、意図した値だけが保存され、対象外の行が更新・削除されないテストを提出してください。
実行前に共通セットアップと各Phaseの確認手順を確認してください。演習コードはwork/で前のPhaseから引き継ぎます。
このフェーズでは、これまでに構築してきたModelに対して、データの永続化(保存・更新・削除)機能をTDDで実装します。
Phase 5.5までで、あなたはすでに以下を実現しています:
- DBからデータを取得できる(all / find / where)
- DBの1行をオブジェクトとして扱える
しかし、まだできていないことがあります:
- 新しいデータを保存する
- 既存のデータを更新する
- データを削除する
このフェーズではそれらを実装します。
以下を説明できる状態になること:
- insert と update の違い
- オブジェクトとDBの状態の違い
- なぜ save というメソッドが必要になるのか
- ORMにおける「状態管理」の難しさ
- 新規レコードを作成できる
- 既存レコードを更新できる
- レコードを削除できる
saveが insert / update を切り替えられる- オブジェクトの状態を元に処理が分岐できる
- Phase 5.5(Finder / Query 共通化)完了
User.all,User.find,User.whereが動作する
user = User.new(name: "Alice", email: "alice@example.com")
user.save
user.name = "Alice Updated"
user.save
user.destroy※ ただし最初からこれを作らないこと ※ 必ず小さなステップで進めること
まずは「新しいデータを保存したい」という要求を固定します。
User.create(...)またはUser.new + save- DBにデータが追加される
-
どちらのAPIから作るか?
createnew + save
👉 どちらでもOK(テストで固定する)
👉 RED
- SQLの
INSERTを実行する - DBにレコードが追加されることを確認する
- IDはどうなるか?
- オブジェクトに反映されているか?
- DBには保存された
- でもオブジェクトはどうなっている?
「保存されたかどうか」がオブジェクトに反映されていない
ここで初めて save の必要性が出ます。
User.new(...).saveができる- DBに保存される
👉 RED
- 新規オブジェクトをINSERTする
- どの時点で「新規」と判断するか?
次に更新処理です。
user = User.find(1)
user.name = "Updated"
user.save- DBが更新されていること
👉 RED
UPDATESQLを書く
- どのレコードを更新するか?
- idはどこから取得するか?
ここで重要な気づき:
- saveはINSERTもUPDATEもする
- どちらをやるか判断が必要
- 新規か既存かどうやって判定するか?
- 新規オブジェクト → INSERT
- 既存オブジェクト → UPDATE
👉 RED
- 内部状態に応じて処理を切り替える
- idの有無
- フラグ
user = User.find(1)
user.destroy- DBから削除される
👉 RED
DELETE FROM ...を実装
- destroy後のオブジェクトはどうなる?
- save後のオブジェクトはどうなる?
「オブジェクトはDBの完全な写像ではない」
- insert / update の共通部分整理
- 属性の取得方法整理
- 過剰な抽象化は禁止
- saveは何をしているのか
- insertとupdateの違い
- なぜ状態管理が必要か
- ORMの難しさはどこにあるか
- true / false にするか?
- 何を意味するか?
user.update(name: "...")- SQLを発行するか?
- 無駄ではないか?
- create / save / update / destroy
- 状態による分岐
- Modelの永続化処理
以下を説明:
- saveは何をしているか
- なぜ状態管理が必要か
- ORMの難しさはどこか
- 今の実装の限界は何か
- TDDが守られているか
- insert / update が正しく分離されているか
- 状態判定が明確か
- 責務が崩れていないか
- 過剰設計になっていないか
→ 内部の分岐を理解することが重要
→ バグの温床
→ 共通化できる部分を見極める
→ 理解が浅くなる
このフェーズで得るべき理解は:
ORMの難しさは「取得」ではなく「状態を持つオブジェクトをDBと同期すること」にある
ここまで来ると、次の違和感が出ます:
- 不正データも保存できてしまう
- ルールがどこにもない
- ドメイン知識がModelにない
次のフェーズでは:
👉 Phase 5.7: バリデーション / モデル責務