長時間調べたが解決方法が見つからないという状態が続きました。
私のミスだったので、同じような状態の人に私の経験を伝えれればと思い書きます。
内容
紐付けしたオブジェクトを削除するために、dependent: :destroy
をつけても、削除できない時に気をつけて欲しいことを書きます。
問題点
ある特定のUserのみ削除できない
モデルの関係性
User
とCart
が親子関係で、
Cart
とProduct
がCart_products
と 1対多 です。
Users ー Carts → Cart_products ← Products
class User < ApplicationRecord
has_one :cart, dependent: :destroy
end
class Cart < ApplicationRecord
belongs_to :user
has_many :cart_products, dependent: :destroy
has_many :products, through: :cart_products
end
class Product < ApplicationRecord
has_many :cart_products, dependent: :destroy
end
class CartProduct < ApplicationRecord
belongs_to :cart
belongs_to :product
end
行っていたこと
関連付けられたオブジェクトもdestroy削除できるように
has_many
,has_one
にdependent: :destroy
をつけていた。
エラー文
Cannot delete or update a parent row: a foreign key constraint fails (`app_name_development`.`cart_products`, CONSTRAINT `fk_rails_a4f3e327f3` FOREIGN KEY (`cart_id`) REFERENCES `carts` (`id`))
原因
User has_one Cart
でUser
にはCart
がは1つのみ紐づくようにしていたのですが、
削除できないUser
には2つのCart
が紐つかれていた。
そのため
User has_one Cart
をUser has_many Carts
と変更すると削除できた。
+----+---------------------+---------------------+---------+
| id | created_at | updated_at | user_id |
+----+---------------------+---------------------+---------+
| 3 | 2020-02-21 07:07:57 | 2020-02-21 07:07:57 | 4 |
| 12 | 2020-02-21 07:29:37 | 2020-02-21 07:29:37 | 7 |
| 13 | 2020-02-21 07:34:26 | 2020-02-21 07:34:26 | 7 |
| 16 | 2020-02-22 07:51:47 | 2020-02-22 07:51:47 | 11 |
+----+---------------------+---------------------+---------+
今後の対処法
モデルを作成する時に、オプションとしてunique: true
を付け、user
の重複をなしにする。
XXXXXXX_create_cart.rb
class CreateCarts < ActiveRecord::Migration[5.2]
def change
create_table :carts do |t|
t.references :user, foreign_key: true, unique: true #ここ
t.timestamps
end
end
end
結論
User has_one Cart
関係の
User
に1つのみのCart
が紐づくようにしていたのですが、
削除できないUser
には2つのCart
が紐つかれていた。
そのため、以下のようにUser has_one Cart
をUser has_many Carts
と変更すると削除できた。
class User < ApplicationRecord
has_one :cart, dependent: :destroy
end
⬇︎
class User < ApplicationRecord
has_many :cart, dependent: :destroy
end