寻求关于优化ActiveRecord :: destroy_all的建议

问题描述 投票:0回答:1

Rails 5 +

[我知道destroy_all实例化每个模型并在其上运行destroy,并且delete_all更快,但是删除不符合要求:

  • [before_destroyaround_destroyafter_destroy回调
  • dependent关系设置

假设列表很全面,我们是否不应该通过检查模型的这些属性来节省destroy_all的时间,如果没有回调,只需根据需要解决关系?

# 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
1个回答
0
投票

回调链可通过_*_callbacks方法访问宾语。活动模型回调支持:before:after:around作为kind属性的值。 kind属性定义回调在链的哪一部分运行。

要在before_save回调链中找到所有回调:

Topic._save_callbacks.select { |cb| cb.kind.eql?(:before) }

因此,在这种情况下,其为_destroy_callbacks,但如果您的目标是健全性检查,则我将使该方法引发异常并保释,而不是调用destroy_all

raise SomeKindOfError if model._destroy_callbacks.any? 

就调试和使用而言,这比埋葬问题要有用得多。

获取模型的所有关联可以通过.reflect_on_all_associations完成,它为您提供了AssocationReflection对象。从那里可以找到关联的选项。

但是...

这有点“聪明”的代码。当您意识到使用回调是性能问题时,存在更大的问题,然后只需选择.reflect_on_all_associationsdelete_all

© www.soinside.com 2019 - 2024. All rights reserved.