class DBPurger::DynamicPlanBuilder

DBPurger::DynamicPlanBuilder generates a purge plan based on the database relations

Constants

INDENT

Attributes

output[R]

Public Class Methods

new(database) click to toggle source
# File lib/db-purger/dynamic_plan_builder.rb, line 10
def initialize(database)
  @database = database
  @output = ''.dup
  @indent_depth = 0
  @tables = []
end

Public Instance Methods

build(base_table_name, field) click to toggle source

rubocop:disable Metrics/AbcSize

# File lib/db-purger/dynamic_plan_builder.rb, line 18
def build(base_table_name, field)
  write_table('base', base_table_name.to_s, field, [], nil)
  line_break
  model = find_model_for_table(base_table_name)
  foreign_key = foreign_key_name(model)
  if model.primary_key == field.to_s
    add_parent_tables(base_table_name, foreign_key)
  else
    add_parent_tables(base_table_name, field)
    unless (child_models = find_child_models(model, foreign_key)).empty?
      line_break unless field == :id
      add_child_tables(child_models, foreign_key, 0)
    end
  end
  ignore_missing_tables
  @output
end

Private Instance Methods

add_child_table(model, field) click to toggle source
# File lib/db-purger/dynamic_plan_builder.rb, line 69
def add_child_table(model, field)
  foreign_key = foreign_key_name(model)
  write_table('child', model.table_name, field, find_child_models(model, foreign_key), foreign_key)
end
add_child_tables(child_models, field, change_indent_by = 1) click to toggle source
# File lib/db-purger/dynamic_plan_builder.rb, line 61
def add_child_tables(child_models, field, change_indent_by = 1)
  @indent_depth += change_indent_by
  child_models.each do |model|
    add_child_table(model, field)
  end
  @indent_depth -= change_indent_by
end
add_parent_tables(base_table_name, field) click to toggle source
# File lib/db-purger/dynamic_plan_builder.rb, line 51
def add_parent_tables(base_table_name, field)
  @database.models.each do |model|
    next if model.table_name == base_table_name.to_s
    next unless column?(model, field)

    foreign_key = foreign_key_name(model)
    write_table('parent', model.table_name, field, find_child_models(model, foreign_key), foreign_key)
  end
end
column?(model, field) click to toggle source
# File lib/db-purger/dynamic_plan_builder.rb, line 88
def column?(model, field)
  model.columns.detect { |c| c.name == field.to_s } != nil
end
find_child_models(model, field) click to toggle source
# File lib/db-purger/dynamic_plan_builder.rb, line 74
def find_child_models(model, field)
  model_has_many_associations(model).map(&:klass).select { |m| column?(m, field) }
end
find_model_for_table(base_table_name) click to toggle source

rubocop:enable Metrics/AbcSize

# File lib/db-purger/dynamic_plan_builder.rb, line 39
def find_model_for_table(base_table_name)
  @database.models.detect { |m| m.table_name == base_table_name.to_s }
end
foreign_key_name(model) click to toggle source
# File lib/db-purger/dynamic_plan_builder.rb, line 84
def foreign_key_name(model)
  model.table_name.singularize + '_id'
end
ignore_missing_tables() click to toggle source
# File lib/db-purger/dynamic_plan_builder.rb, line 103
def ignore_missing_tables
  missing_tables = @database.models.map(&:table_name) - @tables
  return if missing_tables.empty?

  line_break
  missing_tables.each do |table_name|
    write("ignore_table #{table_name.to_sym.inspect}")
  end
end
line_break() click to toggle source
# File lib/db-purger/dynamic_plan_builder.rb, line 47
def line_break
  @output << "\n"
end
model_has_many_associations(model) click to toggle source
# File lib/db-purger/dynamic_plan_builder.rb, line 78
def model_has_many_associations(model)
  model.reflect_on_all_associations.select do |assoc|
    assoc.is_a?(ActiveRecord::Reflection::HasManyReflection)
  end
end
write(str) click to toggle source
# File lib/db-purger/dynamic_plan_builder.rb, line 43
def write(str)
  @output << (INDENT * @indent_depth) + str + "\n"
end
write_table(table_type, table_name, field, child_models, foreign_key) click to toggle source
# File lib/db-purger/dynamic_plan_builder.rb, line 92
def write_table(table_type, table_name, field, child_models, foreign_key)
  @tables << table_name
  if child_models.empty?
    write("#{table_type}_table(#{table_name.to_sym.inspect}, #{field.to_sym.inspect})")
  else
    write("#{table_type}_table(#{table_name.to_sym.inspect}, #{field.to_sym.inspect}) do")
    add_child_tables(child_models, foreign_key)
    write('end')
  end
end