Home Ruby on Rails Tutorial Tutorial Reversible Migration in Rails

Tutorial Reversible Migration in Rails

96
0
SHARE
Tutorial Reversible Migration in Rails
Tutorial Reversible Migration in Rails

In this tutorial we will discuss about reversible migration.

Writing reversible migration is one of the essential skills that a Ruby On Rails developer needs. When we don’t write reversible migration in our projects, it can create a lot of problems in future for database operations. Before learning how to write reversible migrations in our migration files we need to learn to use change method in our code. For instance let’s take a look at the migration method if we would not use the change method

class ProjectUserJoin < ActiveRecord::Migration

 def self.up

create_table :projects_users, :force => true, :id => false do |t|

  t.references :project

  t.references :user

  t.timestamps

end

 end

 

 def self.down

drop_table :projects_users

 end

end

 

The change method

We would have two different methods, one for up and one for down. Back in old version of Rails in 4, this was the way things were done for migrations. We have up definition, we have down definition and they were kept separate in the migration. Up has all the codes that is required when we want to migrate up and down has all the code that is required if we want to migrate down. Now using the shorthand change method you can generate the migrations with lot less code. See the following example

class ProjectUserJoin < ActiveRecord::Migration

 def change

   create_table :projects_users, :force => true, :id => false do |t|

     t.references :project

     t.references :user

     t.timestamps

   end

 end

end

 

The following methods are supported my change method inside the migration

  • create_table => To create a table in database
  • add_column => To add column in database
  • add_index => To add index to column, mostly done for foreign keys for faster database access
  • add_foreign_key => Add foreign key to the table we are creating
  • add_reference => Add foreign key
  • add_timestamps => Add timestamps column to database
  • rename_table => To rename your database table
  • rename_column => To rename your column
  • rename_index => To rename your index

 

If you want your change method to be reversible you need to specify the type of column too as the parameter otherwise it won’t be reversible. For example

class RemoveEmail < ActiveRecord::Migration[5.0]

def change

    remove_column :users, :email, :string

 end

end

 

So why do you think we need to specify that :string in our change method? It is because the down method can drop the column no matter what data type it is but the up method needs this information to create the column of specific data type. For example, if we don’t mention it here then it won’t know if the email field should be string or integer. The same thing exists for dropping the database table. For example consider the table Users , so we need to write the migration as following to be reversible.

class DropUsers < ActiveRecordMigraion[5.0]

def change

    drop_table :users do |u|

       u.string :email

       u.string :password

   end

 end

end

Here in the drop migration, we could have specified only drop_table :users but if we want to create the user table again , then it would be a great problem because we won’t have fields that should be associated with users table. So you need to specify full definition of table for the migration to be reversible.

We have another method in ActiveRecord migration called reversible. This method allows us to write specific code blocks that gets executed during up migrations and down migrations. Let’s look an example

class ChangeProductsPrice < ActiveRecord::Migration[5.0]

 def change

   reversible do |dir|

     change_table :products do |t|

       dir.up   { t.change :price, :string }

       dir.down { t.change :price, :integer }

     end

   end

 end

end

So as discussed, reversible method takes a block and it has up and down methods inside the block. The dir is a block variable. When we go up the down code will be ignored and when we go down the up code will be ignored. Now let’s take another example, say we have a users table in the database and it has the full name column in it. Say it has names like “John Doe”. Now what we want is we want to create two new columns in database and name them first_name and last_name. And we want to save data into them. So first we need to create a table, and then write reversible code

class SplitFullName < ActiveRecord::Migration[5.0]

 

def change

add_column :users, :first_name, :string

add_column :users, :last_name, :string

 

reversible do |dir|

   dir.up do

        User.all.each do |u|

                 u.first_name,u.last_name = u.full_name.split(‘ ‘)

                 u.save

        end

   end

 

   dir.down do

       User.all.each do |u|

                 u.full_name =#{u.first_name} #{u.last_name}

                 u.save

        end

 

   end

remove_column :users, :full_name, :string

 

end

 

end

So here inside the up method we have specified to go to the database and get all of the users and split their full name from space and assigned the first part to first name and last part to last name. And in the down method we have then specified to go to the database and get first name and second name and joined them with space in middle and store into the full name variable.

Note that the add_column, remove_column and such built in methods have already reversible functions built into Rails. If we need to write reversible code for those methods that are not built in we can use reversible method to do so.

 

What to do when we don’t want migration to rollback?

We can specify a standard error called ActiveRecord::IrreversibleMigraion inside our down method, if we don’t want it to revert back. Let’s take a look at an example

class RemoveEmail < ActiveRecord::Migration[5.0]

def up

    remove_column :users, :email, :string

 end

 

def down

   raise ActiveRecord::IrreversibleMigration

end

Now if you try to revert the migration it will raise an error and won’t let that happen. So when we try to go back, the first thing it will call is down method, and the method will raise the error. You can check this with

$ rails db:rollback

 

Conclusion

Migrations should be all reversible. So if we want to change something in our database schema in future we can easily do the hard work without any trouble. If your migrations are irreversible, it can destruct the old database schema as well as won’t let you create new the way you want to.

SHARE
Previous articleRuby on Rails Development
Next articleActiveRecord CRUD operations – Ruby Tutorial
mm
Taichi lover, book addicts, lost himself in the realm of writing code and poetry. Want to talk more? Need help on Ruby on Rails? we can help :)

LEAVE A REPLY

Please enter your comment!
Please enter your name here