How does rails decide if migrations are pending?
Ever wondered how rails decides if any migration is pending? If not, this tutorial will explain how it is done using a table named schema_migrations.
Rails provides a configuration option to indicate if we want to be alerted if any migration is pending.
# Raise an error on page load if there are pending migrations.
config.active_record.migration_error = :page_loadThis will raise an error of the pending migrations and notify the user as shown in the image below.

This can be disabled with the false value
for the option as shown below.
config.active_record.migration_error = falseMigration file name format
There is a convention for naming the migration files.
YYYYMMDDHHMMSS_name_of_migration.rbIt uses values from the current time for YYYYMMDDHHMMSS and the name of the migration.
Once migrations are run, the value YYYYMMDDHHMMSS in migration file,
is inserted in a table named schema_migrations.
Pending migration check
Rails provides a method to check if any migration is pending. Listing relevant methods from ActiveRecord::MigrationContext class below.
# Listing only relevant methods for the illustration
class ActiveRecord
class MigrationContext
def check_pending!(connection = Base.connection)
raise ActiveRecord::PendingMigrationError if connection.migration_context.needs_migration?
end
This piece of code raises an exception ActiveRecord::PendingMigrationError if any migration is pending.
In the next section, we will see the logic used for needs_migration? method.
def needs_migration? # :nodoc:
pending_migration_versions.size > 0
end
def pending_migration_versions # :nodoc:
migrations.collect(&:version) - get_all_versions
end
def migrations # :nodoc:
migrations = migration_files.map do |file|
version, name, scope = parse_migration_filename(file)
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 get_all_versions # :nodoc:
if schema_migration.table_exists?
schema_migration.all_versions.map(&:to_i)
else
[]
end
end
endLogic
migrationsmethod returns versions (YYYYMMDDHHMMSS) of all the migration files available in the application.get_all_versionsmethod returns all the versions available inschema_migrationstablepending_migration_versionsmethod returns the difference between the two arrays mentioned above.
If there is any file with a version that is not availble in the database needs migration
This is the basis of the logic followed for figuring out if any migration is pending. If you liked reading, please subscribe to the newsletter.
Subscribe to Ruby in Rails
Get the latest posts delivered right to your inbox