Migrations are just a small part of what Active Record is capable of. Once you get used to how migrations work, your speed in creating these migrations will increase and become muscle memory like all the other lines of code you have created within Ruby.
Creating a Migration
In order to create a migration, we need to enter code that looks like this:
bundle exec rake db:create_migration NAME=create_my_friends_table
If done correctly, this should have appeared in the terminal:
db/migrate/20220822163630_create_my_friends_table.rb
bundle exec
is used to ensure that there are no compatibility issues between versions. It is a safer practice to use bundle exec even if you are certain your version is working.
After migrating, you create your table like so:
You add your migration to the database with bundle exec rake db:migrate
. It will give you another message that states that the migration was successful. If you did it correctly, you should have seen a message appear showing that the migration was added into the db folder.
After the migration, you should be able to see that a schema has been created for you within the same db
directory and can be viewed. You can check the status of your migration with bundle exec db:migrate:status
. It will show you which migrations status on whether they are active or not.
There are numbers found in the name of the migration that should not be changed or else you will receive errors. They identify that specific migration and also logs when that migration is made. It becomes useful when working with multiple people who need to trace back to a certain migration.
Making Changes After Running the Migration
Rolling back
If you migrated your table, but realized you need to make a change, you can rollback to the previous migration with bundle exec rake db:rollback
. This will change the status from up to down and enable you to make a change. If there were multiple migrations, the most recent one would be removed.
In this case, I did not feel the need to have whether or not I have been talking to my friends. I also decided that there was no need to think about the years of friendship and wanted to add age instead.
When migrating again, we will be able to see the changes go through under the same migration name. The schema also shows this change.
**Note: **If you wanted to rollback multiple migrations, you could use bundle exec db:rollback STEP=<number of migrations back>
Migration methods
Active Record was kind enough to provide us with methods to make changes to our database without needed to completely drop our table and start over again. Here are a list of a few of them:
- add_column
- add_index
- change_column
- change_table
- create_table
- remove_column
- remove_index
- rename_column
We already have seen create_table when we created our table. I will not go over all of them here in detail, but I want you to be aware of the others that exist. For every example, there will be a new migration. Personally, I like being able to create migrations because I want to keep track of all changes I made to my database. I would rather rollback to a previous migration than have to redo an entire table
Adding Columns
If I wanted to add a column to my current migration without rolling back, I would go through the process of creating a new migration, and name that migration based on what I was doing. Therefore, it would be bundle exec rake db:create_migration NAME=add_phone_number_to_friends_table
After that, the syntax within the migration will be different because we are adding a column. It will be add_column :table_name, :column_name, :data_type
. Naming the migration after the table that is being changed helps with organization. I would not want to open up migrations to see where the name of the table appears.
Once you run the migration, it will be updated in the schema and should be placed as the last column.
Removing Columns
If my friends were upset that I placed their age (they would never be they are happy I remember their age but this is just a scenario), I would create another migration to remove the column. I'm sure we know the process of creating migrations for now, so I will show the syntax for removing a column remove_column :table_name, :column_name
If things have been working out for you, the schema will look something like this:
Changing Columns
Even more changes need to be made! We realized we don't want an integer for our phone number, we want a string! We need to once again (and I promise this is the last migration) create a new migration. At least you now are an expert at creating these things! The syntax for this is just as simple as removing and adding columns. change_column :table_name, :column_name, :new_data_type
The final schema should look like this:
If you noticed, the methods all began the same way: identifying the table. This is because without identifying a table, it would not know what table you are looking at. Just because the name of the migration is supposedly linked to the table you are making changes to, it does not mean you are automatically linking the table to the migration. A name is just a name.
Just Drop It
There might be cases where a migration made something irreversible. For instance, you might have destroyed data that no longer can be retrieved, you can always drop the table with bundle exec rake db:drop
to drop the entire database and run migrations all over again to the version you desire. However this might become troublesome with larger databases and is probably best to be avoided if possible.
Note on the other methods:
remove_index
will remove the given index from the table
add_index
will add a new index to the table. Unless you specify, the index will be named after the table and the column name or names (if you added multiple columns each name would be included)
The rename_column
method is in a similar format as change column, but where the datatype is located at is now replaced with the new column name: rename_column :table_name, :column_old_name, :column_new_name
change_table
creates a block to change columns in a table like so:
Resources:
Top comments (3)
In case the article talks about using ActiveRecord in Rails 7 I suggest some small changes:
Replace
bundle exec rake db:create_migration NAME=create_my_friends_table
with
bundle exec rails generate migration CreateMyFriendsTable
Where
CreateMyFriendsTable
is the name of the migration class.See the latest Rails Guides: guides.rubyonrails.org/active_reco...
Replace:
bundle exec rake db:migrate
with
bundle exec rails db:migrate
And in general you can replace
rake
withrails
in all these db-related commands.Also, I see that the documentation you added at the end Migrations points to documentation for Rails v3.2 but I see in the screenshots (the one with the migration file) that you are running at least Rails 6.1 so I suggest to link to a more up to date documentation.
also can write bit shorter:
bundle exec rails g migration CreateMyFriendsTable
and also, not sure why do you use all the time
bundle exec
something is wrong in your project if you need to use it all the time.So, I would mostly use just:
rails g migration CreateMyFriendsTable
Thank you! This was before I was introduced to rails so I was working with what I had. I'm now using rails generate and am loving it!