Migrations are the perfect way for you to create and modify your database in an organized and in well-structured manner. One of the main advantages of migrations is that we don’t have to write SQL queries since migrations provide you with an easy Ruby DSL to Create/Change your table.
Migrations allow us to create tables, add or remove columns, and add indexes to columns. Whenever a migration is generated through a command it is stored in the db/migrate folder of your Rails app directory.
In this post, you'll learn about the following points of migration
-
create_table
-
change_table
-
drop_table
-
DB:rollback
-
add_column
-
rename_column
-
change_column
-
remove_column
-
DB: reset
- DB: seed
Creating a table through migrations
This is how a table is created using migrations. Through the following command, we are generating a Post table within our database with two columns Title and Content.
Remember to use the capitalized name for the table/model name.
$ rails g migration CreatePost title:string content:text
This can also be done as
$ rails g model Post title:string content:text
Both commands would generate the same file with a title consisting of a timestamp and class name followed by the ruby extension. 20200715064057_create_posts.rb
class CreatePosts < ActiveRecord::Migration[5.1]
def change
create_table :posts do |t|
t.string :title
t.text :conent
t.timestamps
end
end
end
The next step is to run
rails db:migrate
Upon running rails db:migrate
a table called posts
with a string column called title
and a text column called content
would be added to db/schema.rb
. An integer column called id
and a column timestampd
will also be added implicitly, it is the default primary key for all Active Record models and timestamp adds two columns, created_at
and updated_at
to the database schema. These two columns are automatically managed by ActiveRecord if their record exists.
*Note - Running rails db:migrate
is mandatory every time a rails migration is added
Usage of ‘text’ or ‘string’ while generating migrations?
As a general rule of thumb, use :string
for short text input (username, email, password, titles, etc.) and use :text
for longer expected input such as descriptions, comment content, etc.
Migration to create a table with reference columns
The need for creating a table like this arises when multiple records in a table are associated with multiple records in another table. For example, there's a Post table and a Tag table. Both tables can have multiple records associated with each other so we need to have a bridge table, PostTag.
$ rails g migration CreatePostTag post:references tag:references
This will generate the following code in a migration file
class CreatePostTags < ActiveRecord::Migration[5.1]
def change
create_table :post_tags do |t|
t.references :post, foreign_key: true
t.references :tag, foreign_key: true
t.timestamps
end
end
end
When we reference a model, index on the foreign_key
is automatically created.
Changing table through migrations
Rename a table with a single Rails migration
I have a Post table within my database but for this reason, I want to change it to Article. Here is how you can do it;
We need to generate a migration through the following command
$ rails generate migration RenamePostToArticle
This will give us an empty migration file, we can modify it ourselves with the following code
class RenameOldTableToNewTable < ActiveRecord::Migration[5.1]
def change
rename_table :posts, :articles #Tables name should be pluralized
end
end
Run rails db:migrate
and you are good to go😎
Let's learn to drop a table from the database.
Through this command, we are generating a migration to remove the Post table including its columns from the database.
$ rails generate migration DropPostTable
The above command would generate an empty migration file, we can edit it with the following code;
class DropPostsTable < ActiveRecord::Migration[5.1]
def up
drop_table :posts
end
def down
raise ActiveRecord::IrreversibleMigration
end
end
Run rails db:migrate
to disappear the Post table from your database.
Rollback a migration
Running plain rails db:rollback
the command would revert the latest migration changes to the database.
But if you want to revert a specific migration you can do it with the following command.
$ rake db:migrate:down VERSION=20200715064057
This will revert the following migration file: db\migrate\20200715064057
_create_posts.rb
Here migration file is identified by its timestamp.
another way of rollback a migration is to use the STEP argument with rails db:rollback
command.
Here is how you can execute this;
$ rake db:rollback STEP=2
In this case, we are defining the number of migration files we want to roll back in a chronological manner.
Command to Add a column to an existing table
We sometimes need to add more columns to our table for our development requirements. The most efficient way of adding a column is to generate a migration.
We need to add a publish
column to our existing Post table. We can do this by running the following command;
$ rails g migration AddPublishToPost publish:boolean
It would give us the following code in the migration file
class AddPublishToPost < ActiveRecord::Migration[5.1]
def change
add_column :posts, :publish, :boolean
end
end
Assigning default value to a column
We can assign a default value to a column by modifying the above file with the following code.
class AddPublishToPost < ActiveRecord::Migration[5.1]
def change
add_column :posts, :publish, :boolean, default: false
end
end
We just added a default: false
key-value pair to make the publish always default upon initializing a new record.
A good way to Rename a column.
Let's change the Post publish
column to status
. To make this change we need to have the following migration generated.
$ rails g migration ChangePublishToStatus
This will give us a migration file with an empty change method. We need to modify the migration file like this;
class ChangePublishToStatus < ActiveRecord::Migration[5.1]
def change
rename_column :posts, :publish, :status
end
end
It will rename the column but keeps the type and content remains the same.
Change Column
Let's learn to change a column type in the most simple and reliable way. In this example, I want to change the publish
column type from boolean
to integer
Run the following command to generate a migration.
rails g migration ChangePostPublish
Edit it like the following file;
class ChangePostPublish < ActiveRecord::Migration[5.1]
def change
reversible do |dir|
change_table :posts do |t|
dir.up { t.change :publish, :integer}
dir.down { t.change :publish, :boolean }
end
end
end
end
It will change the column type.
Remove a Column from the table
Here is how you can remove the column from a table. Let's take an example of the Post table, we want to remove the view
column from it.
Create a migration using the following command
rails g migration RemoveViewFromPost view:integer
It will generate a migration file with the following code. we don't need to modify it.
class RemoveViewFromPost < ActiveRecord::Migration[5.1]
def change
remove_column :posts, :view, :integer
end
end
Running rails db:migrate
would extract and remove the view
column from the Post table.
Reset database
To completely delete and recreate our database, we can either do
$ rake db:reset db:migrate
Which will drop the database and reload the existing schema, or;
$ rake db:drop db:create db:migrate
It will also delete the database, and create a new database as per your database.yml
configuration and migrate it to load the schema.
Seeding databases
Seeding a database is a useful way of populating a database with the basic data needed to make the Rails project run.
Here is how we can create a record of posts using db/seed.rb file
post = Post.create( title: 'A post title',
content: 'This statement is being used as post content.',
publish: true)
Run rails db:seed
to create a record of Posts using seed.
Creating multiple records with a single rails db:seed
command.
iterate over the Post using Ruby Times Loop. Our db/seed.rb file would look like this;
10.times do
post = Post.create( title: 'A post title',
content: 'This statement is being used as post content.',
publish: true)
end
You can also run the seed command to populate the database at the time of creating a database.
$ db:create db:migrate db:seed
Please share this article if you found this useful. I would write more such articles for you to simplify your rails learning.
Read More: Python and Django: Build Powerful Web Applications
Ruby Vs Python: Which will You Choose for Your Next Projects?
Comments (5)