...

/

Anatomy of a Migration

Anatomy of a Migration

Get familiar with the structure and schema of a Rails migration.

Migrations are subclasses of the Rails class ActiveRecord::Migration. When necessary, migrations can contain up() and down() methods, as in lines 2 and 5:

Press + to interact
class SomeMeaningfulName < ActiveRecord::Migration
def up
# ...
end
def down
# ...
end
end

The name of the class, which has all uppercase letters downcased and preceded by an underscore, must match the portion of the filename after the version number. For example, the previous class could be found in a file named 20190425000017_some_meaningful_name.rb. No two migrations can contain classes with the same name.

The up() method is responsible for applying the schema changes for the migration, while the down() method undoes those changes. Let’s make this more concrete. Here’s a migration that adds an e_mail column to the orders table in line 3:

Press + to interact
class AddEmailToOrders < ActiveRecord::Migration
def up
add_column :orders, :e_mail, :string
end
def down
remove_column :orders, :e_mail
end
end

See how the down() method undoes the effect of the up() method? We can also see that there is a bit of duplication here. In many cases, Rails can detect how to automatically undo a given operation. For example, the opposite of add_column() is clearly remove_column() which is used in line 6. In such cases, simply renaming up() to change() can eliminate the need for a down():

Press + to interact
class AddEmailToOrders < ActiveRecord::Migration
def change
add_column :orders, :e_mail, :string
end
end

Now isn’t that much cleaner?

Column types

The third parameter to add_column specifies the type of the database column. In the prior example, we specified that the e_mail column has a type of :string. But what does this mean? Databases typically don’t have column types of :string.

Remember that Rails tries to make our application independent of the underlying database. For example, we could develop using SQLite 3 and deploy to Postgres if we wanted. Different databases use different names for the types of columns, though. If we used a SQLite 3 ...