Active Record Migrations

Migrations can manage the evolution of a schema used by several physical
databases. It's a solution to the common problem of adding a field to
make a new feature work in your local database, but being unsure of how to
push that change to other developers and to the production server. With
migrations, you can describe the transformations in self-contained classes
that can be checked into version control systems and executed against
another database that might be one, two, or five versions behind.

This migration will add a boolean flag to the accounts table and remove it
if you're backing out of the migration. It shows how all migrations
have two methods up and down that describes the
transformations required to implement or remove the migration. These
methods can consist of both the migration specific methods like
add_column and remove_column, but may also
contain regular Ruby code for generating data needed for the
transformations.

Example of a more complex migration that also needs to initialize data:

This migration first adds the system_settings table, then
creates the very first row in it using the Active Record model that relies
on the table. It also uses the more advanced create_table
syntax where you can specify a complete table schema in one block call.

create_table(name, options): Creates a table called
name and makes the table object available to a block that can
then add columns to it, following the same format as
add_column. See example above. The options hash is for
fragments like “DEFAULT CHARSET=UTF-8” that are appended to the create
table definition.

add_column(table_name, column_name, type, options): Adds a new
column to the table called table_name named
column_name specified to be one of the following types:
:string, :text, :integer,
:float, :decimal, :datetime,
:timestamp, :time, :date,
:binary, :boolean. A default value can be
specified by passing an options hash like { default: 11
}. Other options include :limit and :null
(e.g. { limit: 50, null: false }) – see ActiveRecord::ConnectionAdapters::TableDefinition#column
for details.

add_foreign_key(from_table, to_table, options): Adds a new
foreign key. from_table is the table with the key column,
to_table contains the referenced primary key.

remove_timestamps(table_name, options): Removes the timestamp
columns (created_at and updated_at) from the
table definition.

Irreversible transformations

Some transformations are destructive in a manner that cannot be reversed.
Migrations of that kind should raise an
ActiveRecord::IrreversibleMigration exception in their
down method.

Running migrations from within Rails

The Rails package has several tools to help create and apply migrations.

To generate a new migration, you can use

rails generate migration MyNewMigration

where MyNewMigration is the name of your migration. The generator will
create an empty migration file timestamp_my_new_migration.rb
in the db/migrate/ directory where timestamp is
the UTC formatted date and time that the migration was generated.

There is a special syntactic shortcut to generate migrations that add
fields to a table.

rails generate migration add_fieldname_to_tablename fieldname:string

This will generate the file
timestamp_add_fieldname_to_tablename.rb, which will look like
this:

To run migrations against the currently configured database, use
rails db:migrate. This will update the database by running all
of the pending migrations, creating the schema_migrations
table (see “About the schema_migrations table” section below) if missing.
It will also invoke the db:schema:dump task, which will update your
db/schema.rb file to match the structure of your database.

To roll the database back to a previous migration version, use rails
db:migrate VERSION=X where X is the version to which
you wish to downgrade. Alternatively, you can also use the STEP option if
you wish to rollback last few migrations. rails db:migrate
STEP=2 will rollback the latest two migrations.

If any of the migrations throw an
ActiveRecord::IrreversibleMigration exception, that step will
fail and you'll have some manual work to do.

Database support

More examples

Not all migrations change the schema. Some just fix the data:

class RemoveEmptyTags < ActiveRecord::Migration[5.0]
def up
Tag.all.each { |tag| tag.destroy if tag.pages.empty? }
end
def down
# not much we can do to restore deleted data
raise ActiveRecord::IrreversibleMigration, "Can't recover the deleted tags"
end
end

Using a model after changing its table

Sometimes you'll want to add a column in a migration and populate it
immediately after. In that case, you'll need to make a call to
Base#reset_column_information in order to ensure that the
model has the latest column data from after the new column was added.
Example:

This migration will create the horses table for you on the way up, and
automatically figure out how to drop the table on the way down.

Some commands like remove_column cannot be reversed. If you
care to define how to move up and down in these cases, you should define
the up and down methods as before.

If a command cannot be reversed, an
ActiveRecord::IrreversibleMigration exception will be raised
when the migration is moving down.

For a list of commands that are reversible, please see
ActiveRecord::Migration::CommandRecorder.

Transactional Migrations

If the database adapter supports DDL transactions, all migrations will
automatically be wrapped in a transaction. There are queries that you
can't execute inside a transaction though, and for these situations you
can turn the automatic transactions off.

# File activerecord/lib/active_record/migration.rb, line 576defload_schema_if_pending!ifActiveRecord::Migrator.needs_migration?||!ActiveRecord::Migrator.any_migrations?# Roundtrip to Rake to allow plugins to hook into database initialization.FileUtils.cdRails.rootdocurrent_config = Base.connection_configBase.clear_all_connections!system("bin/rails db:test:prepare")
# Establish a new connection, the old database may be gone (db:test:prepare uses purge)Base.establish_connection(current_config)
endcheck_pending!endend

Used to specify an operation that can be run in one direction or another.
Call the methods up and down of the yielded
object to run a block only in one given direction. The whole block will be
called in the right order within the migration.

In the following example, the looping on users will always be done when the
three columns 'first_name', 'last_name' and
'full_name' exist, even when migrating down:

Reverses the migration commands for the given block and the given
migrations.

The following migration will remove the table 'horses' and create
the table 'apples' on the way up, and the reverse on the way down.

class FixTLMigration < ActiveRecord::Migration[5.0]
def change
revert do
create_table(:horses) do |t|
t.text :content
t.datetime :remind_at
end
end
create_table(:apples) do |t|
t.string :variety
end
end
end

Or equivalently, if TenderloveMigration is defined as in the
documentation for Migration: