In migration files, why do the methods in the "down" part have to be in reverse order from "up"?

132 views Asked by At

Using Rails 5.0. It says in the Rails Guide as well as my tutorial that the methods in down should be in the reverse order of up. For example:

class AlterUsers < ActiveRecord::Migration[5.0]
  def up
    rename_table("users", "admin_users")
    add_column("admin_users", "username", :string, :limit =>25, :after => "email")
    change_column("admin_users", "email", :string, :limit => 100)
  end

  def down
    change_column("admin_users", "email", :string, :default => '', :null => false)
    remove_column("admin_users", "username")
    rename_table("admin_users", "users")
  end
end

Note: The methods in down appear in the reverse from the order it was executed in up. i.e: Since change_column was last to be executed from up, is the first to be executed in down.

I understand that down has to undo everything up does for the purpose of allowing you to revert the database to a previous state. I was just wondering whether there was any particular reason for why the methods in down have to be in executed in reverse from the order they were executed in up?

1

There are 1 answers

1
DanneManne On BEST ANSWER

Should is the word to focus on here because it is not always needed, but it is good practice to get into the habit of doing. In practice it is only necessary when the procedures contains migrations that are somewhat related to each other.

To give an example of a migration where the execution order does NOT matter:

class AlterUsers < ActiveRecord::Migration[5.0]
  def up
    add_column "users", "first_name", :string
    add_column "users", "last_name", :string
  end

  def down
    remove_column "users", "first_name"
    remove_column "users", "last_name"
  end
end

In the above example, the two changes does not affect each other at all and even though I have not reversed the order, it will never cause any problems anyway.

But looking at the example in your question, renaming the table that you later add a column to is very much related changes. So if you would not reverse the order in the down method, then it would first rename the table back from "admin_users" to "users" and then try to remove a column from the "admin_users" table that does no longer exist, which would cause the migration to fail. This could of course be easily fixed by adjusting the call to remove_column to remove it from the "users" table, but once you go there, the migrations would become very messy.

TL;DR:

It is not always needed but if you always do it, you are less likely to run into problems because of conflicting migrations.