Class: BulkDependencyEraser::Deleter

Inherits:
Base
  • Object
show all
Defined in:
lib/bulk_dependency_eraser/deleter.rb

Constant Summary collapse

DEFAULT_DB_DELETE_ALL_WRAPPER =
->(deleter, block) do
  begin
    block.call
  rescue BulkDependencyEraser::Errors::DeleterError => e
    deleter.report_error(
      <<~STRING.strip
      Issue attempting to delete klass '#{e.deleting_klass_name}'
        => #{e.original_error_klass.name}: #{e.message}
      STRING
    )
  end
end
DEFAULT_OPTS =
{
  verbose: false,
  # Runs once, all deletions occur within it
  # - useful if you wanted to implement a rollback:
  #   - i.e:
      # db_delete_all_wrapper: lambda do |block|
      #   ActiveRecord::Base.transaction do
      #     begin
      #       block.call
      #     rescue StandardError => e
      #       report_error("Issue attempting to delete '#{current_class_name}': #{e.class.name} - #{e.message}")
      #       raise ActiveRecord::Rollback
      #     end
      #   end
      # end
  db_delete_all_wrapper: self::DEFAULT_DB_DELETE_ALL_WRAPPER,
  db_delete_wrapper: self::DEFAULT_DB_WRITE_WRAPPER,
  # Set to true if you want 'ActiveRecord::InvalidForeignKey' errors raised during deletions
  enable_invalid_foreign_key_detection: false,
  disable_batching: false,
  # a general batching size
  batch_size: 300,
  # A specific batching size for this class, overrides the batch_size
  delete_batch_size: nil,
  # A specific batching size for this class, overrides the batch_size
  disable_delete_batching: nil,
  # Applied to all queries. Useful for taking advantage of specific indexes
  # - not indexed by klass name. Proc would handle the logic for that.
  # - 3rd, and lowest, priority of scopes
  # - accepts rails query as parameter
  # - return nil if no applicable scope.
  proc_scopes: self::DEFAULT_SCOPE_WRAPPER,
  # Applied to all queries. Useful for taking advantage of specific indexes
  # - 2nd highest priority of scopes
  proc_scopes_per_class_name: {},
  # Applied to deletion queries
  # - 1st priority of scopes
  deletion_proc_scopes_per_class_name: {},
}.freeze

Constants inherited from Base

Base::DEFAULT_DB_BLANK_WRAPPER, Base::DEFAULT_DB_READ_WRAPPER, Base::DEFAULT_DB_WRITE_WRAPPER, Base::DEFAULT_KLASS_MAPPED_SCOPE_WRAPPER, Base::DEFAULT_SCOPE_WRAPPER, Base::DEPENDENCY_DESTROY, Base::DEPENDENCY_DESTROY_IGNORE_REFLECTION_TYPES, Base::DEPENDENCY_NULLIFY, Base::DEPENDENCY_RESTRICT, Base::POLY_KLASS_NAME

Instance Attribute Summary

Attributes inherited from Base

#errors

Instance Method Summary collapse

Methods inherited from Base

#merge_errors, #report_error

Methods included from Utils::Methods

#deep_freeze

Constructor Details

#initialize(class_names_and_ids: {}, opts: {}) ⇒ Deleter

Returns a new instance of Deleter.



56
57
58
59
# File 'lib/bulk_dependency_eraser/deleter.rb', line 56

def initialize class_names_and_ids: {}, opts: {}
  @class_names_and_ids = class_names_and_ids
  super(opts:)
end

Instance Method Details

#executeObject



61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/bulk_dependency_eraser/deleter.rb', line 61

def execute
  if opts_c.verbose && opts_c.enable_invalid_foreign_key_detection
    puts "ActiveRecord::Base.connection.disable_referential_integrity - disabled!"
  end

  current_class_name = 'N/A'
  delete_all_in_db do
    begin
      class_names_and_ids.keys.reverse.each do |class_name|
        current_class_name = class_name
        ids = class_names_and_ids[class_name].reverse
        klass = constantize(class_name)

        if opts_c.enable_invalid_foreign_key_detection
          # delete with referential integrity
          delete_by_klass_and_ids(klass, ids)
        else
          # delete without referential integrity
          # Disable any ActiveRecord::InvalidForeignKey raised errors.
          # - src: https://stackoverflow.com/questions/41005849/rails-migrations-temporarily-ignore-foreign-key-constraint
          #        https://apidock.com/rails/ActiveRecord/ConnectionAdapters/AbstractAdapter/disable_referential_integrity
          ActiveRecord::Base.connection.disable_referential_integrity do
            delete_by_klass_and_ids(klass, ids)
          end
        end
      end
    rescue StandardError => e
      raise BulkDependencyEraser::Errors::DeleterError.new(e.class, e.message, deleting_klass_name: current_class_name)
    end
  end

  return errors.none?
end