class ActiveRecord::Migrator

:nodoc:

def current_migration

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

def current_version

def current_version
  sm_table = schema_migrations_table_name
  if Base.connection.table_exists?(sm_table)
    get_all_versions.max || 0
  else
    0
  end
end

def current_version

def current_version
  migrated.max || 0
end

def ddl_transaction(migration)

Wrap the migration in a transaction only if supported by the adapter.
def ddl_transaction(migration)
  if use_transaction?(migration)
    Base.transaction { yield }
  else
    yield
  end
end

def down(migrations_paths, target_version = nil, &block)

def down(migrations_paths, target_version = nil, &block)
  migrations = migrations(migrations_paths)
  migrations.select! { |m| yield m } if block_given?
  self.new(:down, migrations, target_version).migrate
end

def down?

def down?
  @direction == :down
end

def execute_migration_in_transaction(migration, direction)

def execute_migration_in_transaction(migration, direction)
  ddl_transaction(migration) do
    migration.migrate(direction)
    record_version_state_after_migrating(migration.version)
  end
end

def finish

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

def forward(migrations_paths, steps=1)

def forward(migrations_paths, steps=1)
  move(:up, migrations_paths, steps)
end

def get_all_versions

def get_all_versions
  SchemaMigration.all.map { |x| x.version.to_i }.sort
end

def initialize(direction, migrations, target_version = nil)

def initialize(direction, migrations, target_version = nil)
  raise StandardError.new("This database does not yet support migrations") unless Base.connection.supports_migrations?
  @direction         = direction
  @target_version    = target_version
  @migrated_versions = nil
  if Array(migrations).grep(String).empty?
    @migrations = migrations
  else
    ActiveSupport::Deprecation.warn "instantiate this class with a list of migrations"
    @migrations = self.class.migrations(migrations)
  end
  validate(@migrations)
  ActiveRecord::SchemaMigration.create_table
end

def last_migration #:nodoc:

:nodoc:
def last_migration #:nodoc:
  migrations(migrations_paths).last || NullMigration.new
end

def last_version

def last_version
  last_migration.version
end

def migrate(migrations_paths, target_version = nil, &block)

def migrate(migrations_paths, target_version = nil, &block)
  case
  when target_version.nil?
    up(migrations_paths, target_version, &block)
  when current_version == 0 && target_version == 0
    []
  when current_version > target_version
    down(migrations_paths, target_version, &block)
  else
    up(migrations_paths, target_version, &block)
  end
end

def migrate

def migrate
  if !target && @target_version && @target_version > 0
    raise UnknownMigrationVersionError.new(@target_version)
  end
  running = runnable
  if block_given?
    message = "block argument to migrate is deprecated, please filter migrations before constructing the migrator"
    ActiveSupport::Deprecation.warn message
    running.select! { |m| yield m }
  end
  running.each do |migration|
    Base.logger.info "Migrating to #{migration.name} (#{migration.version})" if Base.logger
    begin
      execute_migration_in_transaction(migration, @direction)
    rescue => e
      canceled_msg = use_transaction?(migration) ? "this and " : ""
      raise StandardError, "An error has occurred, #{canceled_msg}all later migrations canceled:\n\n#{e}", e.backtrace
    end
  end
end

def migrated

def migrated
  @migrated_versions ||= Set.new(self.class.get_all_versions)
end

def migrations(paths)

def migrations(paths)
  paths = Array(paths)
  files = Dir[*paths.map { |p| "#{p}/**/[0-9]*_*.rb" }]
  migrations = files.map do |file|
    version, name, scope = file.scan(/([0-9]+)_([_a-z0-9]*)\.?([_a-z0-9]*)?\.rb\z/).first
    raise IllegalMigrationNameError.new(file) unless version
    version = version.to_i
    name = name.camelize
    MigrationProxy.new(name, version, file, scope)
  end
  migrations.sort_by(&:version)
end

def migrations

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

def migrations_path

def migrations_path
  migrations_paths.first
end

def migrations_paths

def migrations_paths
  @migrations_paths ||= ['db/migrate']
  # just to not break things if someone uses: migration_path = some_string
  Array(@migrations_paths)
end

def move(direction, migrations_paths, steps)

def move(direction, migrations_paths, steps)
  migrator = self.new(direction, migrations(migrations_paths))
  start_index = migrator.migrations.index(migrator.current_migration)
  if start_index
    finish = migrator.migrations[start_index + steps]
    version = finish ? finish.version : 0
    send(direction, migrations_paths, version)
  end
end

def needs_migration?

def needs_migration?
  current_version < last_version
end

def open(migrations_paths)

def open(migrations_paths)
  self.new(:up, migrations(migrations_paths), nil)
end

def pending_migrations

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

def proper_table_name(name)

def proper_table_name(name)
  # Use the Active Record objects own table_name, or pre/suffix from ActiveRecord::Base if name is a symbol/string
  if name.respond_to? :table_name
    name.table_name
  else
    "#{ActiveRecord::Base.table_name_prefix}#{name}#{ActiveRecord::Base.table_name_suffix}"
  end
end

def ran?(migration)

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

def record_version_state_after_migrating(version)

def record_version_state_after_migrating(version)
  if down?
    migrated.delete(version)
    ActiveRecord::SchemaMigration.where(:version => version.to_s).delete_all
  else
    migrated << version
    ActiveRecord::SchemaMigration.create!(:version => version.to_s)
  end
end

def rollback(migrations_paths, steps=1)

def rollback(migrations_paths, steps=1)
  move(:down, migrations_paths, steps)
end

def run(direction, migrations_paths, target_version)

def run(direction, migrations_paths, target_version)
  self.new(direction, migrations(migrations_paths), target_version).run
end

def run

def run
  migration = migrations.detect { |m| m.version == @target_version }
  raise UnknownMigrationVersionError.new(@target_version) if migration.nil?
  unless (up? && migrated.include?(migration.version.to_i)) || (down? && !migrated.include?(migration.version.to_i))
    begin
      execute_migration_in_transaction(migration, @direction)
    rescue => e
      canceled_msg = use_transaction?(migration) ? ", this migration was canceled" : ""
      raise StandardError, "An error has occurred#{canceled_msg}:\n\n#{e}", e.backtrace
    end
  end
end

def runnable

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

def schema_migrations_table_name

def schema_migrations_table_name
  SchemaMigration.table_name
end

def start

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

def target

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

def up(migrations_paths, target_version = nil)

def up(migrations_paths, target_version = nil)
  migrations = migrations(migrations_paths)
  migrations.select! { |m| yield m } if block_given?
  self.new(:up, migrations, target_version).migrate
end

def up?

def up?
  @direction == :up
end

def use_transaction?(migration)

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

def validate(migrations)

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