decko-commons/decko

View on GitHub
card/lib/cardio/migration.rb

Summary

Maintainability
A
0 mins
Test Coverage
# -*- encoding : utf-8 -*-

module Cardio
  class Migration < ActiveRecord::Migration[6.1]
    include Assumption
    include Stamp

    class << self
      attr_reader :migration_type, :old_tables, :old_deck_table

      def migration_class type
        type == :schema ? Migration::Schema : Migration::Transform
      end

      def new_for type
        migration_class(type).new
      end

      def port_all
        %i[schema transform].each do |type|
          migration_class(type).port
        end
      end

      def port
        return unless connection.table_exists? old_deck_table
        rename_old_tables
        connection.execute "INSERT INTO #{table} (#{select_nonduplicate_versions})"
        connection.drop_table old_deck_table
      end

      private

      def select_nonduplicate_versions
        "SELECT * FROM #{old_deck_table} o WHERE NOT EXISTS " \
          "(SELECT * FROM #{table} n WHERE o.version = n.version)"
      end

      def rename_old_tables
        old_tables.each do |old_table_name|
          next unless connection.table_exists? old_table_name
          connection.rename_table old_table_name, table
        end
      end

      def table
        "#{migration_type}_migrations"
      end

      def connection
        ActiveRecord::Base.connection
      end
    end

    def migration_type
      self.class.migration_type || :schema
    end

    def run version=nil, verbose=true
      context do |mc|
        ActiveRecord::Migration.verbose = verbose
        mc.migrate version
      end
    end

    def version
      path = stamp_path
      File.exist?(path) ? File.read(path).strip : nil
    end

    def migration_paths
      Cardio.paths["data/#{migration_type}"].existent.to_a
    end

    def context
      mode do |paths|
        yield ActiveRecord::MigrationContext.new(paths, ActiveRecord::SchemaMigration)
      end
    end

    def mode
      with_migration_table { yield migration_paths }
    end

    def down
      raise ActiveRecord::IrreversibleMigration
    end

    private

    def connection
      Cardio::Migration.connection
    end

    def with_migration_table
      yield
    end

    def table_name= table_name
      ActiveRecord::Base.schema_migrations_table_name = table_name
      ActiveRecord::SchemaMigration.table_name = table_name
      ActiveRecord::SchemaMigration.reset_column_information
    end
  end
end