Rails:对象破坏性能

时间:2013-09-29 17:14:40

标签: ruby-on-rails ruby-on-rails-3

在我的rails应用中。我有我的基本模型 - 用户。用户有很多相关的对象。

Class User 
 has_many :contents, dependent: destroy
 has_many :messages, dependent: destroy
 has_many :ratings, dependent: destroy
 has_many :groups, dependent: destroy
 ...
end

当我想从我的系统中删除用户(销毁用户对象)时,需要大约一分钟来销毁其所有关联对象。处理此类案件的最佳方法是什么?

我想到的一种方式是:

在delayed_job中销毁:

但是直到用户对象在延迟作业中被销毁,该用户才不会被其他人看到。通过标记说 - 在用户模型中删除而不是在结果中获取来处理这种情况。但我也使用sphinx,并且需要确保此用户也不会出现sphinx结果。

有没有更好的方法来处理此类案件?

2 个答案:

答案 0 :(得分:2)

挑战在于,正如您可能已经知道的那样,.destroy方法将加载每个子对象,然后调用它们的.destroy方法。

这个值是在进行最终销毁之前评估子节点上的任何回调。因此,如果孩子需要在其他地方清理任何东西,那么它就会这样做。此外,如果依赖对象在destroy方法期间抛出错误,整个销毁操作将回滚,并且您不会最终得到一些半死的对象。

.delete将销毁对象而不将其加载到内存中或执行其回调。然而(显然)它不会执行他们的回调。

如果你想加快速度,你可以像Octopus-Paul所说的那样简单地做dependent: :delete。这样就可以了,但是它不会破坏这些对象上的依赖项,因此,例如,如果组中有与之关联的消息,或者评级中有与之关联的注释,那么这些对象都不会被销毁。

为了确保所有下游家属都被销毁并且任何必要的回调都得到尊重,我认为您可以做的最好的事情是编写一个自定义before_destroy方法,该方法可以清除所有内容,但使用.delete和{{ 1}}以加快速度。

这将产生遗留问题,因为有人编写下游代码并不一定会预测您的方法,但您可以判断其风险。另一种选择(正如你所说)是使用一个标志并异步完成工作。我想这将来风险较小,但今天实施的成本可能更高。

答案 1 :(得分:0)

:依赖

控制关联对象在其所有者被销毁时会发生什么:

:destroy causes the associated object to also be destroyed
:delete causes the associated object to be deleted directly from the database (so callbacks will not execute)

删除速度会快得多,因为它只会为已删除用户的每个关联运行数据库查询。

在此处查找更多选项:http://guides.rubyonrails.org/association_basics.html#options-for-has-one-dependent