Create idempotent data migrations

Alireza Bashiri
Feb 2 · 2 min read

You’re working on a long-term Ruby on Rails project and as requirements change you find out that you should remove one of the models or associations in database design terms. Hmm, seems easy right?!

After finishing your refactoring you write a migration to change data from an old model to a new one

Now you remove the model SubscriptionReward and test, commit and push but wait how’s this migration supposed to work with SubscriptonReward model being removed? THE ANSWER IS IT WON’T.

So how should we write a data migration from an old model to a new one?

Using raw SQL + Rails migration. We’re going to use ActiveRecord::Base.connection.select_all to run a raw SQL query on old database schema and pass it down to the new one.

ActiveRecord::Base.connection.select_all returns ActiveRecord::Result which is an Enumerable

In all of this, is any room left for more polishing? YES. As you can see we’re dropping subscription_rewards table what if there’s no subscription_rewards table? here comes if_exists flag argument which we can pass to drop_table method to avoid running a DROP TABLE on a non-existent table which leads to DROP TABLE IF EXIST

Recently if_not_exists flag argument added to drop_table method which the opposite version to avoid running a CREATE TABLE for an already existing table which you can give look here
https://github.com/rails/rails/pull/31382


Thanks for reading and hope you’ve enjoyed your time.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade