Rails 3.1 - Changes in Migrations

With the release of Rails 3.1, a lot has changed. Migrations saw quite a few changes that I really like and I wanted to share them here. Migrations have always been one of my favorite parts of Rails because they make managing your database tables a breeze and with Rails 3.1 it gets even easier.

Migrations in Rails 3.1 has moved the #up and #down methods to instance methods instead of class methods. This just feels better to me when writing migrations.

1 class MyAwesomeMigration < ActiveRecord::Migration
2     def up
3       # some change you want to make goes here
4     end
6     def down
7       # revert the change you made in the up action
8     end
9   end

Then, the Rails team took it one step further. Since most migrations are just doing the reverse in the down action as what was done in the up action they have introduced the #change action. When defined in your migration this combines both the up and down actions into a single method call.

I. Heart. This.

It always felt like 90% of the migrations that I was writing didn't need a separate definition for the down action. I wanted Rails to just figure out that "if I'm creating a table in the up, then drop it in the down" or "if I'm adding a column then remove it" or "if I'm changing a column then change it back". Well, now that happens for us thanks to the new ActiveRecord::Migration::CommandRecorder class. I've added a few examples to show you how simple your migrations can now be.

 1 # Add/Drop a table
 2   class MyAwesomeMigration < ActiveRecord::Migration
 3     def change
 4       create_table(:users) do |t|
 5         t.string :first_name
 6         t.string :last_name
 7         t.timestamps
 8       end
 9     end
10   end
12   # Add/Remove a table column
13   class MyAwesomeMigration < ActiveRecord::Migration
14     def change
15       add_column :users, :birthdate, :date
16     end
17   end
19   # Rename a column in a table
20   class MyAwesomeMigration < ActiveRecord::Migration
21     def change
22       rename_column :users, :birthdate, :birthday
23       # This one is a bit interesting because when the reverse is called
24       # the arguments you specify are simply reversed. So this would be the "down"
25       # action
26       #
27       #    rename_column :users, :birthday, :birthdate
28     end
29   end

Obviously, not everything can be reversed. For example, how would you logically reverse removing a column? At first you might think "that's easy, just call add_column on the down action". The only problem with that is when you call `remove_column' you don't specify the type for the column. That means when the `add_column' action is called it will fail. Not to worry, Rails will alert you if you have tried to do something it has deemed irreversible. An `IrreversibleMigration' exception will be raised.

Here is a list of the actions that are auto-magically reversed. The reverse action is given inside the parenthesis:

Another change that was made to keep in line with the new #change method is that when you create a migration from a constructive migration generator, the change method will be used in place of the up and down methods. Wondering what a "constructive migration generator" is? Here's and example:

#=> rails g migration AddFirstNameToUsers first_name:string
1 # The following migration is created
2   class AddFirstNameToUsers < ActiveRecord::Migration
3     def change
4       add_column :users, :first_name, :string
5     end
6   end

And there you have it. Migrations in Rails 3.1 are even more awesome than they used to be. So get out there and try these techniques for yourself.

Something missing? Need more explanation? Let me know in the c-c-c-comments!

blog comments powered by Disqus