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
5
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
11
12 # Add/Remove a table column
13 class MyAwesomeMigration < ActiveRecord::Migration
14 def change
15 add_column :users, :birthdate, :date
16 end
17 end
18
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:
- add_column (remove_column)
- add_index (remove_index)
- add_timestamps (remove_timestamps)
- create_table (drop_table)
- remove_timestamps (add_timestamps)
- rename_column
- rename_index
- rename_table
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