delete_all vs destroy_all?

时间:2011-07-14 18:32:14

标签: ruby-on-rails ruby database activerecord

我正在寻找从表中删除记录的最佳方法。例如,我有一个用户,其用户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函数,但我只是想确认正确的方法。

4 个答案:

答案 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选项可以在线上或线下正常工作,实例化并销毁所有相关记录,从而触发回调。