Class: BulkDependencyEraser::Nullifier
- Defined in:
- lib/bulk_dependency_eraser/nullifier.rb
Constant Summary collapse
- DEFAULT_DB_NULLIFY_ALL_WRAPPER =
->(nullifier, block) do begin block.call rescue BulkDependencyEraser::Errors::NullifierError => e nullifier.report_error( <<~STRING.strip Issue attempting to nullify klass '#{e.}' on column(s) '#{e.}' => #{e.original_error_klass.name}: #{e.} 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_nullify_all_wrapper: lambda do |block| # ActiveRecord::Base.transaction do # begin # block.call # rescue StandardError => e # report_error("Issue attempting to nullify '#{current_class_name}': #{e.class.name} - #{e.message}") # raise ActiveRecord::Rollback # end # end # end db_nullify_all_wrapper: self::DEFAULT_DB_NULLIFY_ALL_WRAPPER, db_nullify_wrapper: self::DEFAULT_DB_WRITE_WRAPPER, # Set to true if you want 'ActiveRecord::InvalidForeignKey' errors raised during nullifications # - I can't think of a use-case where a nullification would generate an invalid key error # - Not hurting anything to leave it in, but might remove it in the future. 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 nullify_batch_size: nil, # A specific batching size for this class, overrides the batch_size disable_nullify_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 nullification queries # - 1st priority of scopes nullification_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
Instance Method Summary collapse
-
#combine_matching_columns(nullification_hash) ⇒ Object
Combine columns if the IDs are the same - will do one SQL call instead of several.
- #execute ⇒ Object
-
#initialize(class_names_columns_and_ids:, opts: {}) ⇒ Nullifier
constructor
-
structure: { <model_name>: { column_name: <array_of_ids> } }.
-
Methods inherited from Base
Methods included from Utils::Methods
Constructor Details
#initialize(class_names_columns_and_ids:, opts: {}) ⇒ Nullifier
-
structure:
{ <model_name>: { column_name: <array_of_ids> } }
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
# File 'lib/bulk_dependency_eraser/nullifier.rb', line 66 def initialize class_names_columns_and_ids:, opts: {} @class_names_columns_and_ids = class_names_columns_and_ids super(opts:) if opts_c.verbose puts "Combining nullification column groups (if groupable)" puts "Before Combination: #{@class_names_columns_and_ids}" end @class_names_columns_and_ids = combine_matching_columns(@class_names_columns_and_ids) if opts_c.verbose puts "After Combination: #{@class_names_columns_and_ids}" end end |
Instance Method Details
#combine_matching_columns(nullification_hash) ⇒ Object
Combine columns if the IDs are the same
-
will do one SQL call instead of several
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
# File 'lib/bulk_dependency_eraser/nullifier.rb', line 84 def combine_matching_columns(nullification_hash) return {} if nullification_hash.none? merged_hash = {} nullification_hash.each do |klass_name, columns_and_ids| merged_hash[klass_name] = {} columns_and_ids.each do |key, array| sorted_array = array.sort # Find any existing key in merged_hash that has the same sorted array matching_key = merged_hash[klass_name].keys.find { |k| merged_hash[klass_name][k].sort == sorted_array } if matching_key # Concatenate the matching keys and update the hash new_key = key.is_a?(Array) ? key : [key] if matching_key.is_a?(Array) new_key += matching_key else new_key << matching_key end merged_hash[klass_name][new_key] = sorted_array merged_hash[klass_name].delete(matching_key) else # Otherwise, just add the current key-value pair merged_hash[klass_name][key] = sorted_array end end end merged_hash end |
#execute ⇒ Object
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 |
# File 'lib/bulk_dependency_eraser/nullifier.rb', line 118 def execute current_class_name = 'N/A' current_column = 'N/A' nullify_all_in_db do begin # column_and_ids should have already been reversed in builder class_names_columns_and_ids.keys.reverse.each do |class_name| current_class_name = class_name klass = class_name.constantize columns_and_ids = class_names_columns_and_ids[class_name] columns_and_ids.each do |column, ids| current_column = column # Reversing IDs. Last ones in are more likely to be dependencies, and should be deleted first. ids = ids.reverse if opts_c.enable_invalid_foreign_key_detection # nullify with referential integrity nullify_by_klass_column_and_ids(klass, column, ids) else # nullify 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 nullify_by_klass_column_and_ids(klass, column, ids) end end end end rescue StandardError => e raise BulkDependencyEraser::Errors::NullifierError.new( e.class, e., nullifying_klass_name: current_class_name, nullifying_columns: current_column.to_s # could be an array, string, or symbol ) end end return errors.none? end |