Database Migrations
what should I do when not using rails
- tags
- database
- node
- activerecord
- golang
Contents
Keeping track of database changes over time is best done using database migrations stored in a code repository. I'm working on something where programs in different languages will be access the same database, so here we are going to look at 3 different solutions to track changes that aren't tied to a specific framework.
We're going to setup a postgres database – with pgadmin
so we can see
what's going on – and then do the same execersizes with 3 different
ways to manage changes.
Setup the databases
Lets get our test environment up and running:
Using docker-compose.yaml
:
|
|
Then
|
|
And finally create the test databases:
|
|
We have out three databases now, so it's time to run through the contenders!
Node: db-migrate
First we'll create a node project to load the db-migrate
module with
the postgres adapter. I try very hard not to install things globally,
so this will happen within a project.
|
|
Now we need to create a database.json
file, which tells db-migrate
how
to connect to the database.
|
|
Creating a table
|
|
Then open up the created migration in the migrations
folder, and change the up
function to be:
|
|
Then:
|
|
Renaming a column
|
|
Then in the new migration:
|
|
And then do the migration again:
|
|
Thoughts
Probably I'm being foolish by not installing this globally, but there
you go. You can choose to have db-migrate
use SQL files or write the
changes in javascript. Doing it in JavaScript gives you options to
switch databases, to use SQLite for example in development. In
practice this is is rarely done, but its a nice option.
I found the documentation of db-migrate
to be unhelpful. It could use
more examples and I was a bit bewildered at first even though it
turned out to be straightforward to get working.
Ruby: ActiveRecord
Lets see how to use ActiveRecord to handle migrations, but without using rails.
First we need to make sure that we have a ruby environment with the correct gems installed:
|
|
Now we setup our database.yml
:
|
|
And we can make a Rakefile
to give us a similar usage pattern as you'd
get with rails:
|
|
This is a handy task runner also, so you could stick more tasks in there as time goes on. Here you can see the ones that are defined.
|
|
Creating a table
Create the template:
|
|
And then fill out the migration itself:
|
|
And finally run it:
|
|
Renaming a column
|
|
And edit the resulting migration:
|
|
And then run it:
Schema dump
The rakefile will also extract what it knows about the database and
put it in the db/schema.rb
file, which ends up like:
|
|
Which is handy if you are used to rails. The rake db:reset
function
is also pretty handy.
Thoughts
This is the style that I'm more used to, so I'm biased. However one
thing I really like is that it will create the database for you if
need it, and db:reset
often comes in handy. Feels much more user
friendly than the node version does.
Go: golang-migrate
Another interesting option is to use the migrate
tool which is written
in go. This can be run as a standalone cli (so similar to db-migrate
in that respect) but also embedded in your go programs, running on
startup perhaps as needed.
This also packaged up as a docker image, so we don't need it install
anything locally if we don't want to, which I don't, so lets create a
quick script migrate
to run the command:
|
|
You could also just install the CLI.
The rest here is adapted from the Postgres tutorial.
Create a table
First we generate our templates:
|
|
And then in put our sql in the generated file
migrations/000001_create_urls.up.sql
:
|
|
To run the migration itself we are going to pass the database connect string as an environment variable first, and then run the migration:
|
|
Renaming a column
Create our template:
|
|
Slap the sql into the new file:
|
|
And run:
|
|
Thoughts
This feels like the cleanest "standalone" tool. Writing database
specific sql feels like a bit of a throwback but honestly at a certain
point you'll need to get into that level on control. The docker image
is only 35.1MB
and anything with node or ruby is generally in the 100s
of MB, which is probably fine overall but feels a bit excessive for
something this seemingly simple.
Conclusion
I like the Rakefile
based solution the best, since it gives me both
more functionality out of the box (db create and reset, schema
definitions), it's a good place to add other tasks, and, let's
acknowledge it, I'm the most familiar with it.
Of the three, the go one feels the most "serious" and feels like where I'll end up in the long run, so if you were to pick one I'd in general recommend that.
|
|
References
- https://github.com/db-migrate/node-db-migrate
- https://db-migrate.readthedocs.io/en/latest/Getting%20Started/usage/
- https://itnext.io/updating-an-sql-database-schema-using-node-js-6c58173a455a
- https://www.devdungeon.com/content/ruby-activerecord-without-rails-tutorial#toc-9
- https://gist.github.com/Rhoxio/ee9a855088c53d447f2eb888bd9d09a4
- https://github.com/golang-migrate/migrate/blob/master/database/postgres/TUTORIAL.md
Previously
Next