1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Rails】nested attributesの完全ガイド(更新・新規・削除を一括処理)

1
Posted at

はじめに

Railsで親子関係のあるデータ(例:会員と「好きなもの」「嫌いなもの」)を扱う際、親レコードの更新と一緒に子レコードも一括で保存・削除したいケースは頻繁にあります。

この記事では、Railsの accepts_nested_attributes_for を使用して、画面上での「更新・新規作成・削除」をDBへ正確に反映させる仕組みと、React側でのデータ構築方法について解説します。

この記事でわかる・できること

  • nested attributes を使った子レコード削除(_destroy)の仕組み
  • 親子関係のデータを1回のリクエストで安全に整合性を保って更新する方法
  • フロントエンド(React)からRailsへ送るべきデータ構造の具体的な実装

この記事の対象者

  • Railsで親子関係のフォーム作成に悩んでいる方
  • 画面で削除した項目がDBから消えずに困っている方
  • ReactなどのSPAからRailsの nested attributes を利用したい方

動作環境・使用するツールや言語

  • Rails: 7.0以上
  • Ruby: 3.2以上
  • React: 18以上

1. nested attributes とは

Railsには、親モデルを通じて子モデルを保存・更新する機能があります。これを nested attributes と呼びます。

基本的な構造

例えば Member(会員)が複数の Like(好きなもの)を持っている場合:

Member
 ├─ likes(ラーメン、カレー)
 └─ dislikes(パクチー)

通常はそれぞれ個別に保存処理が必要ですが、この機能を使うと Member の保存時に likes や dislikes もまとめて処理できるようになります。

Rails側の設定

モデルに accepts_nested_attributes_for を定義し、allow_destroy: true を付けることが重要です。
これがないと削除機能が動作しません。

/model/member.rb
class Member < ApplicationRecord
  has_many :likes, dependent: :destroy
  has_many :dislikes, dependent: :destroy

  # allow_destroy: true が削除処理に必須
  accepts_nested_attributes_for :likes, allow_destroy: true
  accepts_nested_attributes_for :dislikes, allow_destroy: true
end

2. 子レコード削除の仕組み(_destroy)

画面上で「削除」ボタンを押したとき、単にフォームから消すだけではDB上のレコードは消えません。Railsに「削除命令」を送る必要があります。

削除に必要なデータ形式

削除したいレコードに対して、以下の形式でパラメータを送ります。

likes_attributes: [
  { id: 5, _destroy: true }
]
  • id: どのレコードか特定する
  • _destroy: true: このレコードを削除するという命令

これにより、「画面上の削除」と「DB上の削除」が一致します。

3. React側でのデータ構築ロジック

ここからは、フロントエンド(React)からRails APIへリクエストを送る際の、データ構築の実装例です。

「更新」「新規」「削除」の3つの状態を、1つの配列(attributes)にまとめるのがポイントです。

実装コード(React)

const likesAttrs = [
  // 1. 更新または新規作成の処理
  ...editLikes.map((like) =>
    like.id 
      ? { id: like.id, name: like.name } // IDがある = 既存レコードの更新
      : { name: like.name }              // IDがない = 新規作成
  ),
  // 2. 削除の処理
  ...removedLikeIds.map((id) => ({ id, _destroy: true })),
];

ロジックの分解解説

① 更新と新規の判別

editLikes(画面に残っているリスト)をマップします。

  • id がある場合: { id: 5, name: "ラーメン" }
    • Railsは「ID:5 のレコード名を更新」と判断します。
  • id がない場合: { name: "カレー" }
    • Railsは「新しいレコードを作成」と判断します。

② 削除データの追加

removedLikeIds(削除ボタンが押されたIDリスト)をマップします。

  • 削除対象: { id: 7, _destroy: true }
    • Railsは「ID:7 のレコードを削除」と判断します。

完成するパラメータのイメージ

上記ロジックを通すと、Railsには以下のような配列が届きます。

likes_attributes: [
  { id: 5, name: "ラーメン" }, // 更新
  { name: "カレー" },          // 新規作成
  { id: 7, _destroy: true }    // 削除
]

まとめ

nested attributes を使いこなすことで、複雑な親子関係のデータ操作をシンプルかつ安全に行うことができます。

  1. Rails側: accepts_nested_attributes_for に allow_destroy: true をつける
  2. 削除の仕組み: 対象の id と _destroy: true をセットで送る
  3. データ構築: 「更新・新規・削除」を1つの配列にまとめてAPIへ送信する

この設計パターンは、Railsフォーム設計の核心部分であり、API開発においても非常に有効な手段です。

参考資料

Railsガイド: accepts_nested_attributes_for

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?