My last Clojure post covered some TDD, this post is going to discuss how I added migrations and a deployment to Heroku to that same application. I’ve been teaching myself Clojure by rebuilding my simple personal website, so I was cheating a little bit as I already had a database with tables and columns. The first thing I would need to do when deploying was to migrate the table-less database so my application could use it. I looked at a few of the Clojure migration libraries but it got me thinking: why couldn’t I use the Rails ActiveRecord migrations library? I was familiar with it, it would not be a runtime requirement and I’ve often thought of how to build polyglot applications. This was my chance to exercise that, so I looked at how to use ActiveRecord migrations standalone.
Looking through the Rails codebase, you see that all the interesting data definition language (DDL) stuff is in the connection adapters, and in the active_record/migration module. Then there’s the Rake tasks and the Rails generators. It turns out it’s a little more coupled to Rails then you might first think. However there are blog posts which describe how to solve this, and also a Gem, standalone_migrations which does the required plumbing, which I managed to get up and running without too much drama.
source 'https://rubygems.org'
gem 'standalone_migrations'
gem 'activerecord-postgresql-adapter'
The standalone-migrations
library uses slightly different conventions from Rails for where the database configuration is, which is fine except when trying to deploy to Heroku. Heroku depends on build packs which describe how to setup the virtual machine that the application will run on. The Ruby build back expects the file config/database.yml
in order to inject the production database settings, but fortunately there is some configuration for standalone_migrations
that will allow for a different file location.
> cat .standalone_migrations
config:
database: config/database.yml
Now new migrations can be created without using the Rails generators, and the usual db:migrate
tasks can be run to change the schema.
Right now, when deploying to Heroku, it’s gone from thinking it’s a Clojure application to thinking it’s a Ruby application. It runs through checks to see which build pack to use, and we’ve added just enough to make Heroku think that this is a Ruby application. We can set the Clojure build pack through configuration, but we won’t have the required dependencies installed of for our migrations. This is where the multi build pack, comes in handy.
First we set the build pack:
heroku config:add BUILDPACK_URL=https://github.com/ddollar/heroku-buildpack-multi.git
Then configure that build pack to use both Clojure and Ruby build packs:
> cat .buildpacks
https://github.com/heroku/heroku-buildpack-clojure.git
https://github.com/heroku/heroku-buildpack-ruby.git
Now we can run migrations, and deploy our Clojure application. Welcome to the beginnings of the polyglot application.