【发布时间】:2020-03-26 23:54:49
【问题描述】:
Rails 5+
我知道 destroy_all 实例化每个模型并在其上运行 destroy 并且 delete_all 更快,但删除不尊重:
-
before_destroy、around_destroy和after_destroy回调 -
dependent关系设置
假设这个列表很全面,我们不应该通过检查模型的这些属性来节省destroy_all 的时间吗?如果没有回调,只需根据需要处理关系吗?
编辑:我正在寻找一种方法来修改默认的destroy_all 行为,以便它更智能并且不会盲目地实例化所有对象并链接到依赖关系的调用。如果我们有 A 与依赖 B (1:1) 的关系,并且 A 很大(1 百万),那么需要实例化和销毁很多对象。是的,特定于应用程序/领域的知识意味着您可以调用delete_all,但如果有人更改模型并添加关系,那么delete_all 就会变得非常危险。如果我们优化destroy_all 做一些思考,我们可以将一个简单的dependent: delete 关系减少为来自关系A 上的单个destroy_all 的两个delete_all 调用(A 和B),其中原始destroy_all 将是2百万对象实例化和数据库命中。
# Pseudocode
# Let the model in question be `User`
ids = self.pluck(:id)
if model.has_destroy_callbacks # I imagine there's some fancy introspection stuff I can use
original_destroy_all
return
else
# Check Restrict type
model.restrict_relationships.each do |rel|
other_models = some_cute_query
raise_exception_or_add_error if other_models.any?
end
# Add some check here to make sure we didn't miss any unknown dependency type
# Normal relationships
model.non_restrict_relationships.each do |rel|
dep_type = rel.dependent_type
if dep_type == :destroy
rel.where(model_id: ids).destroy_all
elsif dep_type == :delete
rel.where(model_id: ids).delete_all
elsif dep_type == :nullify
rel.where(model_id: ids).update_all(model_name_id: nil)
end
end
end
self.delete_all # i.e. the collection that was gonna get destroyed
我正在寻找的是健全性检查,如果我遗漏了一些明显的东西,为什么这不起作用。我也在寻找有关如何将其放入 ActiveRecord 的建议。另外,您能否针对特定模型的集合/关系专门覆盖 destroy_all?
【问题讨论】:
标签: ruby-on-rails activerecord ruby-on-rails-5 rails-activerecord