Rails 6删除User时触发FOREIGN KEY约束失败的解决方案
Rails 6删除用户时触发外键约束报错的解决方法
报错场景
在Rails 6应用中执行User实例销毁操作时,触发SQLite外键约束异常,完整报错日志如下:
irb(main)> u = User.last => #<User id: 43, email: [FILTERED], ...> irb(main)> u.destroy (0.0ms) SELECT sqlite_version(*) TRANSACTION (0.0ms) begin transaction Folder Destroy (0.7ms) DELETE FROM "folders" WHERE "folders"."id" = ? [["id", 43]] TRANSACTION (0.1ms) rollback transaction /sqlite3/statement.rb:108:in `step': SQLite3::ConstraintException: FOREIGN KEY constraint failed (ActiveRecord::InvalidForeignKey) /sqlite3/statement.rb:108:in `step': FOREIGN KEY constraint failed (SQLite3::ConstraintException)
原有模型配置
需求为删除用户时,同步删除其关联的Folder和Article资源,原有相关模型代码如下:
User模型
class User < ApplicationRecord has_many :folders, dependent: :destroy has_many :articles, through: :folders after_destroy :destroy_articles private def destroy_articles self.articles.destroy_all end end
Folder模型
# /app/models/folder.rb class Folder < ApplicationRecord belongs_to :user has_many :articles validates :name, presence: true, uniqueness: { scope: :user_id } end
Article模型
# /app/models/article.rb class Article < ApplicationRecord belongs_to :user belongs_to :folder validates :title, presence: true validates :link, presence: true, uniqueness: { scope: :user_id } end
问题根源
Article表存在指向Folder表的外键关联,删除Folder前未先清除关联的Article记录,直接触发外键约束导致删除失败。而原有User模型的after_destroy回调执行时机晚于Folder销毁操作,事务已经回滚,回调逻辑不会生效。
修复方案
在Folder模型中新增销毁前回调,删除Folder前先销毁其关联的所有Article,修改后的Folder模型代码如下:
# /app/models/folder.rb class Folder < ApplicationRecord before_destroy :destroy_articles belongs_to :user has_many :articles private def destroy_articles self.articles.destroy_all end end
优化方案(可选)
无需手动编写回调,直接在Folder的关联配置上添加dependent: :destroy即可实现相同效果,代码更简洁:
class Folder < ApplicationRecord belongs_to :user has_many :articles, dependent: :destroy # 其余原有逻辑保持不变 end
内容的提问来源于stack exchange,提问作者Brad West
相关产品推荐
相关产品推荐

