Rails migrations: self.up and self.down versus change
Ruby on-RailsMigrationRails ActiverecordRails MigrationsRuby on-Rails Problem Overview
Looks like the new rails version has "change" versus self.up and self.down methods.
So what happens when one has to roll back a migration how does it know what actions to perform. I have the following method that I need to implement based on an online tutorial:
class AddImageToUsers < ActiveRecord::Migration
def self.up
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
def self.down
remove_column :users, :image_file_name, :string
remove_column :users, :image_content_type, :string
remove_column :users, :image_file_size, :integer
remove_column :users, :image_updated_at, :datetime
end
end
How can I do the same using the new change method?
Ruby on-Rails Solutions
Solution 1 - Ruby on-Rails
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 - Ruby on-Rails
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 - Ruby on-Rails
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