-
Notifications
You must be signed in to change notification settings - Fork 84
Concepts
Ragtime needs an implementation of the ragtime.core/Migratable
protocol to tell it how to migrate a particular database.
As an example, we'll create a Migratable in-memory database:
(require '[ragtime.core :as ragtime])
(defrecord MemoryDatabase [data migrations]
ragtime/Migratable
(add-migration-id [_ id]
(swap! migrations conj id))
(remove-migration-id [_ id]
(swap! migrations (partial filterv (complement #{id}))))
(applied-migration-ids [_]
(seq @migrations)))
(defn memory-database []
(->MemoryDatabase (atom {}) (atom [])))
We can define an new instance of this database, and see that it is empty, and has no migrations:
user=> (def db (memory-database))
#'user/db
user=> (-> db :data deref)
{}
user=> (ragtime/applied-migrations db)
nil
Migrations are maps that contain three keys:
-
:id
- a unique ID for the migration -
:up
- a function that applies the migration to a database -
:down
- a function that rolls back the migration in a database
Here's an example of one that modifies the MemoryDatabase
defined earlier.
(def add-foo
{:id "add-foo"
:up (fn [db] (swap! (:data db) assoc :foo 1))
:down (fn [db] (swap! (:data db) dissoc :foo))})
We can apply a migration to a database using the migrate
function:
user=> (ragtime/migrate db add-foo)
["add-foo"]
user=> (ragtime/applied-migration-ids db)
("add-foo")
user=> (-> db :data deref)
{:foo 1}
And remove a migration using rollback
:
user=> (ragtime/migrate db add-foo)
[]
user=> (ragtime/applied-migration-ids db)
nil
user=> (-> db :data deref)
{}
Often we'll want to work with migrations that have already been applied to the database. For example, we may wish to roll back the latest migration. The Migratable
protocol provides a way of finding the IDs of the migrations applied to the database, but we need some way of associating these IDs with the migrations themselves. In other words, we need a migration index.
An index simply maps IDs to migrations. We can create an index for a collection of migrations by using the into-index
function:
user=> (def idx (ragtime/into-index [add-foo]))
#'user/idx
user=> idx
{"add-foo" {:id "add-foo", :up ..., :down ...}}
Once we have an index, we can use the migrate-all
function to update the database with an ordered collection of migrations:
user=> (ragtime/migrate-all db idx [add-foo])
nil
user=> (ragtime/applied-migration-ids db)
("add-foo")
Or to roll back the last migrations applied to the database:
user=> (ragtime/rollback-last db idx)
nil
user=> (ragtime/applied-migration-ids db)
nil