我正在寻找从表中删除记录的最佳方法。例如,我有一个用户,其用户ID跨越许多表。我想删除此用户以及在所有表中都有其ID的每条记录。
u = User.find_by_name('JohnBoy')
u.usage_indexes.destroy_all
u.sources.destroy_all
u.user_stats.destroy_all
u.delete
这可以从所有表中删除用户的所有引用,但我听说destroy_all
过程非常繁重,所以我尝试了delete_all
。它只将用户从他自己的用户表中删除,并且所有其他表中的id
都为空,但保留记录不变。有人可以分享执行此类任务的正确流程吗?
我看到destroy_all
在所有相关对象上调用destroy
函数,但我只是想确认正确的方法。
答案 0 :(得分:215)
你是对的。如果要删除用户和所有关联对象 - > destroy_all
但是,如果您只想删除用户而不取消所有关联对象 - > delete_all
根据这篇文章:Rails :dependent => :destroy VS :dependent => :delete_all
destroy
/ destroy_all
:通过调用destroy方法将相关对象与此对象一起销毁delete
/ delete_all
:立即销毁所有关联对象,而不调用它们:destroy方法答案 1 :(得分:21)
delete_all是一个SQL DELETE语句,仅此而已。 destroy_all在所有匹配结果上调用destroy():条件(如果有的话),这些结果可能至少为NUM_OF_RESULTS个SQL语句。
如果您必须在大型数据集上执行诸如destroy_all()之类的极端操作,我可能不会从应用程序执行此操作并小心处理它。如果数据集足够小,你就不会受到太大伤害。
答案 2 :(得分:16)
为了避免destroy_all
实例化所有记录并一次销毁一个记录,您可以直接从模型类中使用它。
所以而不是:
u = User.find_by_name('JohnBoy')
u.usage_indexes.destroy_all
你可以这样做:
u = User.find_by_name('JohnBoy')
UsageIndex.destroy_all "user_id = #{u.id}"
结果是一个查询来销毁所有相关记录
答案 3 :(得分:1)
我做了一个small gem,可以减轻在某些情况下手动删除相关记录的需要。
这个gem为ActiveRecord关联添加了一个新选项:
dependent :: delete_recursively
当您销毁记录时,将使用此选项关联的所有记录将被递归删除(即跨模型),而不会实例化任何记录。
请注意,就像dependent :: delete或dependent :: delete_all一样,这个新选项不会触发依赖记录的around / before / after_destroy回调。
但是,有可能具有依赖::在与模式链相关联的模型链中的任何位置销毁关联:: delete_recursively。 :destroy选项可以在线上或线下正常工作,实例化并销毁所有相关记录,从而触发回调。