class PG::Schema::Migrator

Constants

MIGRATION_FILE_REGEX

Attributes

connection[RW]
directory[RW]

Public Class Methods

new(db:, directory: nil, log: Logger.new(STDOUT)) click to toggle source
# File lib/pg/schema-migration.rb, line 65
def initialize(db:, directory: nil, log: Logger.new(STDOUT))
  @db        = db
  @directory = directory
  @log       = log

  load_migration_files
  generate_schema_migration_table!
end

Public Instance Methods

apply(version, direction) click to toggle source
# File lib/pg/schema-migration.rb, line 101
def apply(version, direction)
  migration = PG::Schema.get_migration_by_version(version)
  commands  = migration.public_send(direction)

  commands.reverse! if direction == :down

  @db.transaction do
    commands.each do |command|
      @db.exec(command)
    end
  end

  update_version(direction == :up ? version : version - 1)
rescue => error
  @log.error error.message
  @log.info  "The migration failed. Current version #{current_version}"
  raise
end
current_version() click to toggle source
# File lib/pg/schema-migration.rb, line 153
      def current_version
        res = @db.exec <<~SQL
          SELECT version FROM schema_information
        SQL

        raise "Schema information has multiple values" if res.ntuples > 1

        res.field_values("version").first.to_i
      end
generate_schema_migration_table!() click to toggle source
# File lib/pg/schema-migration.rb, line 135
      def generate_schema_migration_table!
        @db.exec <<~SQL
          CREATE TABLE IF NOT EXISTS schema_information (
            version INTEGER DEFAULT 0 NOT NULL
          )
        SQL

        if @db.exec("SELECT * FROM schema_information").ntuples.zero?
          @db.exec <<~SQL
            INSERT INTO schema_information DEFAULT VALUES
          SQL
        end
      end
load_migration_files() click to toggle source
# File lib/pg/schema-migration.rb, line 120
def load_migration_files
  files = []

  if directory
    Dir.new(directory).sort.each do |file|
      next unless file.match(MIGRATION_FILE_REGEX)
      file = File.join(directory, file)
      files << file
      load(file)
    end
  end

  files
end
run!(version: nil) click to toggle source
# File lib/pg/schema-migration.rb, line 74
def run!(version: nil)
  migrations       = PG::Schema.migrations
  _current_version = current_version

  version||= migrations.count

  if version == _current_version || migrations.empty?
    @log.info "Nothing to do."
    return
  end

  t = Time.now
  @log.info "Migrationg from #{_current_version} to version #{version}"
  if version > _current_version
    (_current_version + 1).upto(version) do |target|
      apply(target, :up)
    end
  else
    (_current_version).downto(version + 1) do |target|
      apply(target, :down)
    end
  end

  @log.info "Finished applying migration #{version}, took #{sprintf('%0.6f', Time.now - t)} seconds"
  @log.info "Done!"
end
update_version(version) click to toggle source
# File lib/pg/schema-migration.rb, line 149
def update_version(version)
  @db.exec("UPDATE schema_information SET version = $1", [version])
end