discourse/migrations/lib/converters/base/converter.rb
Gerhard Schlager 89f26da39d
MT: Switch to nested module style across migrations/ (#38564)
Ruby's compact module syntax (`module
Migrations::Database::Schema::DSL`) breaks lexical constant lookup —
`Module.nesting` only includes the innermost constant, so every
cross-module reference must be fully qualified. In practice this means
writing `Migrations::Database::Schema::Helpers` even when you're already
inside `Migrations::Database::Schema`.

Nested module definitions restore the full nesting chain, which brings
several practical benefits:

- **Less verbose code**: references like `Schema::Helpers`,
`Database::IntermediateDB`, or `Converters::Base::ProgressStep` work
without repeating the full path from root
- **Easier to write new code**: contributors don't need to remember
which prefixes are required — if you're inside the namespace, short
names just work
- **Fewer aliasing workarounds**: removes the need for constants like
`MappingType = Migrations::Importer::MappingType` that existed solely to
shorten references
- **Standard Ruby style**: consistent with how most Ruby projects and
gems structure their namespaces

The diff is large but mechanical — no logic changes, just module
wrapping and shortening references that the nesting now resolves.
Generated code (intermediate_db models/enums) keeps fully qualified
references like `Migrations::Database.format_*` since it must work
regardless of the configured output namespace.

- Convert 138 lib files from compact to nested module definitions
- Remove now-redundant fully qualified prefixes and aliases
- Update model and enum writers to generate nested modules with correct
indentation
- Regenerate all intermediate_db models and enums
2026-03-19 18:15:19 +01:00

91 lines
2.2 KiB
Ruby

# frozen_string_literal: true
module Migrations
module Converters
module Base
class Converter
attr_accessor :settings
def initialize(settings)
@settings = settings
end
def run(only_steps: [], skip_steps: [])
if respond_to?(:setup)
puts "Initializing..."
setup
end
create_database
filter_steps(steps, only_steps, skip_steps).each do |step_class|
step = create_step(step_class)
before_step_execution(step)
execute_step(step)
after_step_execution(step)
end
rescue SignalException
STDERR.puts "\nAborted"
exit(1)
ensure
Database::IntermediateDB.close
end
def steps
step_class = Step
current_module = self.class.name.deconstantize.constantize
current_module
.constants
.map { |c| current_module.const_get(c) }
.select { |klass| klass.is_a?(Class) && klass < step_class }
.sort_by(&:to_s)
end
def before_step_execution(step)
# do nothing
end
def execute_step(step)
executor =
if step.is_a?(ProgressStep)
ProgressStepExecutor
else
StepExecutor
end
executor.new(step).execute
end
def after_step_execution(step)
# do nothing
end
def step_args(step_class)
{}
end
private
def create_database
db_path = File.expand_path(settings[:intermediate_db][:path], Migrations.root_path)
Database.migrate(db_path, migrations_path: Database::INTERMEDIATE_DB_SCHEMA_PATH)
db = Database.connect(db_path)
Database::IntermediateDB.setup(db)
end
def create_step(step_class)
default_args = { settings: }
args = default_args.merge(step_args(step_class))
step_class.new(StepTracker.new, args)
end
def filter_steps(step_classes, only_steps, skip_steps)
ClassFilter.filter(step_classes, only: only_steps, skip: skip_steps)
end
end
end
end
end