Rails 5 +
Я знаю, что destroy_all
создает экземпляр каждой модели и запускает на ней destroy
и что delete_all
быстрее, но удаление не относится:
before_destroy
, around_destroy
и after_destroy
обратные вызовы dependent
настройки отношений
Предполагая, что этот список является всеобъемлющим, разве мы не сможем сэкономить время с помощью destroy_all
, проверив эти свойства модели и, если нет обратных вызовов, просто обратиться к нужным отношениям?
edit: я ищу способ изменить поведение по умолчанию destroy_all
так что это умнее и не создает вслепую все объекты и цепные вызовы зависимых отношений. Если у нас есть отношения A с зависимой B (1: 1), а A большой (1 мил), это много объектов для создания и уничтожения. Да, знание приложения / домена c означает, что вы можете просто позвонить delete_all
, но если кто-то изменит модель и добавит отношения, delete_all
просто станет очень опасным. Если мы оптимизируем destroy_all
для некоторого размышления, мы можем уменьшить простое отношение dependent: delete
до двух delete_all
вызовов (A и B) из одного destroy_all
отношения A, где исходный 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
для коллекций / отношений в указанных c моделях?