Systematize your database— The Ruby way to be the croupier of migrations.
Ever wondered how the croupiers do that shuffle when they separate the card deck in two and just mix both piles into one? I’ve tried that multiple times and the cards just flew everywhere 😞. But now imagine that you could do that shuffling with your data and structure migrations, aligning them to run in the order they should…That would be a cool thing!
While your application starts getting bigger and bigger, probably so does your migration folder and with that you’ll probably need to move some data around different tables, or even change such data because your structure changed as well.
When do you run your migrations? First the data migrations and then the structure migrations or the other way around?
With any of those approaches some errors are prone to happen:
- On the first approach (data → structure) what would you do, if the field that you need isn’t created yet (because the structure migration hasn’t run)?
- On the second approach (structure → data) what would you do, if the field that you want to populate needs data from another field that is deleted on the structure migration?
Let me show you an example:
- Let’s say you have a
Post
model with a boolean attribute named:deleted
that represents the deletedPosts
; - After some time, and some deleted
Posts
, you are asked to instead of just knowing that aPost
was deleted we also need to know when thePost
was deleted. So you create the:deleted_at
field that will contain the date it was deleted; - Now you create the data migration that searches all the deleted
Posts
and timestamps the:deleted_at
field. So far so good; - After that is done you can safely remove the old and obsolete
:deleted
field.
So with this example we have 2 structural migrations (creating the :deleted_at
field and deleting the :deleted
field) and 1 data migration (populating the :deleted_at
field). It’s all peachy and dandy until you run your migrations because when you finish running the structural ones you will not have a :deleted
field to query the Posts
that were deleted.
With this in mind let me introduce you to Systematize, the gem that will make that pain go away.
How does it work?
Just add it to your Gemfile:
#Gemfile
gem 'systematize', '~> 0.0.1'
or install it via bundler
bundle install 'systematize'
Surprise, surprise you have some shinny new tasks!
$> bundle exec rake -T
rake systematize:migrate # Migrate the database
rake systematize:rollback # Rollback the database (options: STEP=x, VERBOSE=false)
rake systematize:rollback_all # Rollback all the database
With this your migrations will be re-arranged and they will run in the timespan order to make sure that all goes peachy keen!
It’s not all fun and games you know?
For this to go smoothly as it should you just need to respect some rules:
- The migrations need to be in the correct folder, for structural migrations it should be
db/migrate
and the data migrations should live indb/data
. Like this:
- app
|
|-db
|-data
|-migrate
- The migrations need to follow the Rails convention
YYYYMMDDHHMMSS_create_products.rb
Time to shine
Now if you need to migrate the database you just need to run:
bundle exec rake systematize:migrate
Needing to rollback the previous migration? No problem.
bundle exec rake systematize:rollback
Need to rollback 2/3/4 migrations? I got you.
bundle exec rake systematize:rollback STEP=2
Made a mess so big you need to start fresh? Do it. (the migrations need to be reversible 😅)
bundle exec rake systematize:rollback_all
Don’t forget to smash that 💚 button and if you have anything to say, just drop like it’s hot @RicBrazao!
Hacker Noon is how hackers start their afternoons. We’re a part of the @AMI family. We are now accepting submissions and happy to discuss advertising & sponsorship opportunities.
If you enjoyed this story, we recommend reading our latest tech stories and trending tech stories. Until next time, don’t take the realities of the world for granted!