Anatomy of a Migration
Get familiar with the structure and schema of a Rails migration.
We'll cover the following...
Migrations are subclasses of the Rails class ActiveRecord::Migration
. When necessary, migrations can contain up()
and down()
methods, as in lines 2 and 5:
class SomeMeaningfulName < ActiveRecord::Migrationdef up# ...enddef down# ...endend
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:
class AddEmailToOrders < ActiveRecord::Migrationdef upadd_column :orders, :e_mail, :stringenddef downremove_column :orders, :e_mailendend
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()
:
class AddEmailToOrders < ActiveRecord::Migrationdef changeadd_column :orders, :e_mail, :stringendend
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 ...