Migration in Rails is a tool that allows the developer to use Ruby to change an application's database schema. Instead of using SQL scripts, we use Ruby code, which is database independent, so it is easy to move the application to a completely new platform. We define these database changes in domain-specific language (DSL), and these migrations can be rolled back and managed along with the application source code.
In Ruby, the db/migrate
folder contains all the migrations in the form of files. The name of the file is in the form YYYYMMDDHHMMSS_name_of_migration.rb
, which is the UTC timestamp followed by the name of the migration. One important point to remember here is that the migration class name should match the later part of the file name. For instance, 20220906120001_add_details_to_orders.rb
should define the class AddDetailsToOrders
(CamelCased).
Using migration, we can create tables, add indexes on columns, and add or remove columns.
Example of Migration in Rails
Let's see an example to understand migration better:
rails generate migration CreateEvents department:string
The above command creates a migration that creates table events
in our database. And a timestamped Ruby file, 20221119103635_create_events.rb
, is also created in the db/migrate
directory.
A Ruby file would have the following contents:
class CreateEvents < ActiveRecord::Migration[5.7]
def change
create_table :events do |t|
t.string :department
t.timestamps
end
end
end
Let's examine the code shown above:
- The migration file class
CreateEvents
inherits from superclassActiveRecord::Migration[5.7]
.5.7
describes the Rails version here. - Then we have the method
change
that containsdomain-specific language (DSL)
to manipulate the database. In this scenario, thechange
method is anevent
table with a columndepartment
of type string. t.timestamps
is used in the code to add timestampscreated_at
andupdated_at
to theevents
table.
Rails Migration Errors
Occasionally, while running a migration, it trips up. It can fail for a variety of reasons, such as incorrect syntax or an invalid database query, among others.
Example: Duplicate Column Error
"rake aborted!
StandardError: An error has occurred, this and all later migrations canceled:
PG::DuplicateColumn: ERROR: column "department" of relation "events" already exists"
In any event, we need to handle failure and get past it. To address this issue, Rails executes each migration as part of a transaction. As a result, anytime a transaction fails, the transaction is rolled back, preventing the database from becoming inconsistent.
4 Tips to Prevent Migration Errors
- Roll Back A Migration
The most popular method is to just roll back a migration using
rails db:rollback
and attempt to complete the migration by resolving the issue, similar to the above-mentioned duplicate column error. - Clean Up Old Migrations
It's a good idea to clean up old migrations when we can't run migrations on a new database (
rails db:migrate
). Poorly written migrations might be creating migration failure. Here, cleaning up means deleting files from thedb/migrations
folder. - Avoid Irreversible Migrations
We should always make sure that our migration is reversible, i.e., we can run
rails db:rollback
on it. - Use Temporary Rake Tasks
Migration in Rails should only be used for schema changes and not for changes to existing data. So whenever dealing with complex data migrations, it's a good idea to create temporary rake tasks. This way, we can keep the deployment separate from the data changes.
Track, Analyze and Manage Errors With Rollbar
Managing errors and exceptions in your code is challenging. It can make deploying production code an unnerving experience. Being able to track, analyze, and manage errors in real-time can help you proceed with more confidence. Rollbar automates error monitoring and triaging, making fixing Ruby errors easier than ever. Try it today!