123456789_123456789_123456789_123456789_123456789_

Class: ActiveRecord::Migrator

Do not use. This class is for internal use only.
Relationships & Source Files
Inherits: Object
Defined in: activerecord/lib/active_record/migration.rb

Constant Summary

Class Attribute Summary

Class Method Summary

Instance Attribute Summary

Instance Method Summary

Constructor Details

.new(direction, migrations, schema_migration, internal_metadata, target_version = nil) ⇒ Migrator

[ GitHub ]

  
# File 'activerecord/lib/active_record/migration.rb', line 1415

def initialize(direction, migrations, schema_migration, , target_version = nil)
  @direction         = direction
  @target_version    = target_version
  @migrated_versions = nil
  @migrations        = migrations
  @schema_migration  = schema_migration
  @internal_metadata = 

  validate(@migrations)

  @schema_migration.create_table
  @internal_metadata.create_table
end

Class Attribute Details

.migrations_paths (rw)

[ GitHub ]

  
# File 'activerecord/lib/active_record/migration.rb', line 1401

attr_accessor :migrations_paths

Class Method Details

.current_version

For cases where a table doesn’t exist like loading from schema cache

[ GitHub ]

  
# File 'activerecord/lib/active_record/migration.rb', line 1404

def current_version
  connection = ActiveRecord::Tasks::DatabaseTasks.migration_connection
  schema_migration = SchemaMigration.new(connection)
   = InternalMetadata.new(connection)

  MigrationContext.new(migrations_paths, schema_migration, ).current_version
end

Instance Attribute Details

#down?Boolean (readonly, private)

[ GitHub ]

  
# File 'activerecord/lib/active_record/migration.rb', line 1573

def down?
  @direction == :down
end

#invalid_target?Boolean (readonly, private)

Return true if a valid version is not provided.

[ GitHub ]

  
# File 'activerecord/lib/active_record/migration.rb', line 1518

def invalid_target?
  @target_version && @target_version != 0 && !target
end

#up?Boolean (readonly, private)

[ GitHub ]

  
# File 'activerecord/lib/active_record/migration.rb', line 1569

def up?
  @direction == :up
end

#use_advisory_lock?Boolean (readonly, private)

[ GitHub ]

  
# File 'activerecord/lib/active_record/migration.rb', line 1590

def use_advisory_lock?
  connection.advisory_locks_enabled?
end

Instance Method Details

#connection (private)

[ GitHub ]

  
# File 'activerecord/lib/active_record/migration.rb', line 1483

def connection
  ActiveRecord::Tasks::DatabaseTasks.migration_connection
end

#current

Alias for #current_migration.

[ GitHub ]

  
# File 'activerecord/lib/active_record/migration.rb', line 1436

alias :current :current_migration

#current_migration Also known as: #current

[ GitHub ]

  
# File 'activerecord/lib/active_record/migration.rb', line 1433

def current_migration
  migrations.detect { |m| m.version == current_version }
end

#current_version

[ GitHub ]

  
# File 'activerecord/lib/active_record/migration.rb', line 1429

def current_version
  migrated.max || 0
end

#ddl_transaction(migration, &block) (private)

Wrap the migration in a transaction only if supported by the adapter.

[ GitHub ]

  
# File 'activerecord/lib/active_record/migration.rb', line 1578

def ddl_transaction(migration, &block)
  if use_transaction?(migration)
    connection.transaction(&block)
  else
    yield
  end
end

#execute_migration_in_transaction(migration) (private)

[ GitHub ]

  
# File 'activerecord/lib/active_record/migration.rb', line 1522

def execute_migration_in_transaction(migration)
  return if down? && !migrated.include?(migration.version.to_i)
  return if up?   &&  migrated.include?(migration.version.to_i)

  Base.logger.info "Migrating to #{migration.name} (#{migration.version})" if Base.logger

  ddl_transaction(migration) do
    migration.migrate(@direction)
    record_version_state_after_migrating(migration.version)
  end
rescue => e
  msg = +"An error has occurred, "
  msg << "this and " if use_transaction?(migration)
  msg << "all later migrations canceled:\n\n#{e}"
  raise StandardError, msg, e.backtrace
end

#finish (private)

[ GitHub ]

  
# File 'activerecord/lib/active_record/migration.rb', line 1543

def finish
  migrations.index(target) || migrations.size - 1
end

#generate_migrator_advisory_lock_id (private)

[ GitHub ]

  
# File 'activerecord/lib/active_record/migration.rb', line 1610

def generate_migrator_advisory_lock_id
  db_name_hash = Zlib.crc32(connection.current_database)
  MIGRATOR_SALT * db_name_hash
end

#load_migrated

[ GitHub ]

  
# File 'activerecord/lib/active_record/migration.rb', line 1478

def load_migrated
  @migrated_versions = Set.new(@schema_migration.integer_versions)
end

#migrate

[ GitHub ]

  
# File 'activerecord/lib/active_record/migration.rb', line 1446

def migrate
  if use_advisory_lock?
    with_advisory_lock { migrate_without_lock }
  else
    migrate_without_lock
  end
end

#migrate_without_lock (private)

Used for running multiple migrations up to or down to a certain value.

[ GitHub ]

  
# File 'activerecord/lib/active_record/migration.rb', line 1497

def migrate_without_lock
  if invalid_target?
    raise UnknownMigrationVersionError.new(@target_version)
  end

  record_environment
  runnable.each(&method(:execute_migration_in_transaction))
end

#migrated

[ GitHub ]

  
# File 'activerecord/lib/active_record/migration.rb', line 1474

def migrated
  @migrated_versions || load_migrated
end

#migrations

[ GitHub ]

  
# File 'activerecord/lib/active_record/migration.rb', line 1465

def migrations
  down? ? @migrations.reverse : @migrations.sort_by(&:version)
end

#pending_migrations

[ GitHub ]

  
# File 'activerecord/lib/active_record/migration.rb', line 1469

def pending_migrations
  already_migrated = migrated
  migrations.reject { |m| already_migrated.include?(m.version) }
end

#ran?(migration) ⇒ Boolean (private)

[ GitHub ]

  
# File 'activerecord/lib/active_record/migration.rb', line 1513

def ran?(migration)
  migrated.include?(migration.version.to_i)
end

#record_environment (private)

Stores the current environment in the database.

[ GitHub ]

  
# File 'activerecord/lib/active_record/migration.rb', line 1507

def record_environment
  return if down?

  @internal_metadata[:environment] = connection.pool.db_config.env_name
end

#record_version_state_after_migrating(version) (private)

[ GitHub ]

  
# File 'activerecord/lib/active_record/migration.rb', line 1559

def record_version_state_after_migrating(version)
  if down?
    migrated.delete(version)
    @schema_migration.delete_version(version.to_s)
  else
    migrated << version
    @schema_migration.create_version(version.to_s)
  end
end

#run

[ GitHub ]

  
# File 'activerecord/lib/active_record/migration.rb', line 1438

def run
  if use_advisory_lock?
    with_advisory_lock { run_without_lock }
  else
    run_without_lock
  end
end

#run_without_lock (private)

Used for running a specific migration.

[ GitHub ]

  
# File 'activerecord/lib/active_record/migration.rb', line 1488

def run_without_lock
  migration = migrations.detect { |m| m.version == @target_version }
  raise UnknownMigrationVersionError.new(@target_version) if migration.nil?

  record_environment
  execute_migration_in_transaction(migration)
end

#runnable

[ GitHub ]

  
# File 'activerecord/lib/active_record/migration.rb', line 1454

def runnable
  runnable = migrations[start..finish]
  if up?
    runnable.reject { |m| ran?(m) }
  else
    # skip the last migration if we're headed down, but not ALL the way down
    runnable.pop if target
    runnable.find_all { |m| ran?(m) }
  end
end

#start (private)

[ GitHub ]

  
# File 'activerecord/lib/active_record/migration.rb', line 1547

def start
  up? ? 0 : (migrations.index(current) || 0)
end

#target (private)

[ GitHub ]

  
# File 'activerecord/lib/active_record/migration.rb', line 1539

def target
  migrations.detect { |m| m.version == @target_version }
end

#use_transaction?(migration) ⇒ Boolean (private)

[ GitHub ]

  
# File 'activerecord/lib/active_record/migration.rb', line 1586

def use_transaction?(migration)
  !migration.disable_ddl_transaction && connection.supports_ddl_transactions?
end

#validate(migrations) (private)

[ GitHub ]

  
# File 'activerecord/lib/active_record/migration.rb', line 1551

def validate(migrations)
  name, = migrations.group_by(&:name).find { |_, v| v.length > 1 }
  raise DuplicateMigrationNameError.new(name) if name

  version, = migrations.group_by(&:version).find { |_, v| v.length > 1 }
  raise DuplicateMigrationVersionError.new(version) if version
end

#with_advisory_lock (private)

[ GitHub ]

  
# File 'activerecord/lib/active_record/migration.rb', line 1594

def with_advisory_lock
  lock_id = generate_migrator_advisory_lock_id

  got_lock = connection.get_advisory_lock(lock_id)
  raise ConcurrentMigrationError unless got_lock
  load_migrated # reload schema_migrations to be sure it wasn't changed by another process before we got the lock
  yield
ensure
  if got_lock && !connection.release_advisory_lock(lock_id)
    raise ConcurrentMigrationError.new(
      ConcurrentMigrationError::RELEASE_LOCK_FAILED_MESSAGE
    )
  end
end