2013-09-29 116 views
0

在我的Rails应用程序中。我有我的基本模型 - 用户。有很多关联的对象给用户。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的破坏:

但直到点用户对象获取延迟就业摧毁,该用户不应该为别人看到。处理这种情况是通过在用户模型中标记一个标记来删除,而不是在结果中提取。但是我也使用狮身人面像,并且需要确保这个用户不会出现狮身人面像结果。

有没有更好的方法来处理这种情况?

+0

一种选择是首先销毁用户,并将相关对象的销毁委托给延迟作业。 – tihom

+1

你考虑过使用'delete'而不是'destroy'吗?http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html – gabrielhilal

+1

@gabrielhilal肯定。但在删除的情况下,观察者回调不会发生,我将不得不手动执行它们。就像摧毁用户会破坏团队一样,团队又必须更新计数并删除组中的活动。分开处理它们会使代码变得复杂。但那是这样吗? –

回答

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

+0

谢谢@八达通保罗。但是我的关联对象又有它自己的联系。像组有很多活动。所以摧毁团体必须摧毁其协会。 –

+0

在这种情况下,您不能使用:删除:D – cristian

2

的挑战是,正如你可能已经知道,.destroy方法将加载每个孩子对象,然后调用其.destroy方法。

其中的值是在进行最终销毁之前对孩子的任何回调进行评估。所以如果一个孩子需要在其他地方清理任何东西,那么它会这样做。同样,如果依赖对象在销毁方法期间抛出错误,则整个销毁操作将会回滚,并且最终不会导致一些半死对象的跛行。

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

如果你想加快速度,你可以简单地按照Octopus-Paul的建议做dependent: :delete。这样可以,但是它不会破坏这些对象的依赖关系,例如,如果组有消息与它们相关联,或者评级有与它们相关的评论,那么这些消息都不会被销毁。

为了确保所有下游的家属被摧毁任何必要的回调很荣幸,我认为你能做的最好是写一个自定义的before_destroy方法,完成了所有清理,但为了加快速度使用.delete.delete_all

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