Rails migrations: self.up and self.down versus change

Solution 1:

For many operations rails can guess what is the inverse operation (without problems). For example, in your case what is the reverse operation of add_column to call when you rollback? Of course it's remove_column. What is the inverse of create_table? It's drop_table. So in these cases rails know how to rollback and define a down method is superfluous (you can see in the documentation the methods currently supported from the change method).

But pay attention because for some kind of operation you still need to define the down method, for example if you change the precision of a decimal column how to guess the original precision on rollback? It's not possible, so you need to define the down method.

As said, I suggest you to read the Rails Migrations Guide.

Solution 2:

Better to use Up, Down, Change:

On Rails 3 (Reversible): which should add new column on up and fill all records in table only on up, and only delete this column on down

def up
  add_column :users, :location, :string
  User.update_all(location: 'Minsk')
end

def down
  remove_column :users, :location
end

But:

You had to avoid using change method which allows to save some time. For example, if you didn’t need to update column value immediately after it’s adding you would cut this code down to like this:

def change
  add_column :users, :location, :string
end

On up it will add column to table and remove it on down. Much less code and it’s a profit.

On Rails 4: one more useful way to write what we need in one place:

def change
  add_column :users, :location, :string
  reversible do |direction|
    direction.up { User.update_all(location: 'Minsk') }
  end
end

Solution 3:

class AddImageToUsers < ActiveRecord::Migration
  def change
    add_column :users, :image_file_name, :string
    add_column :users, :image_content_type, :string
    add_column :users, :image_file_size, :integer
    add_column :users, :image_updated_at, :datetime
  end
end