-
Notifications
You must be signed in to change notification settings - Fork 84
Concepts
Migrations consist of a map of two one-argument functions, :up
and :down
, and a unique identifier, :id
.
Here's an example of one that modifies an in-memory atom stored in (:data db)
:
(def add-dog
{:id "add-dog"
:up (fn [db] (swap! (:data db) conj :dog))
:down (fn [db] (swap! (:data db) disj :dog))})
You can apply a migration to a database using the migrate
function, and remove a migration using rollback
. Ragtime will maintain a list of applied migrations which you can access with the applied-migrations
function:
(migrate db add-dog)
(applied-migrations db)
=> [add-dog]
(rollback db add-dog)
(applied-migrations db)
=> []
The database itself needs to be a type that implements the
ragtime.core/Migratable
protocol. If we wanted an in-memory database
that wrapped an atom, we might implement it as a record:
(defrecord MemoryDatabase [data]
(add-migration-id [_ id]
(swap! data update-in [:migrations] conj id))
(remove-migration-id [_ id]
(swap! data update-in [:migrations]
(vec (remove (partial = id) %))))
(applied-migration-ids [_]
(seq (:migrations @data))))
(defn memory-database []
(MemoryDatabase. (atom {:migrations []})))
It's important that applied-migration-ids
maintains the order
migrations were applied in, which is why we're using a vector in this
example.
The ragtime.sql library includes a SqlDatabase
record that can be used
to wrap a database connection map. For instance:
#ragtime.sql.database.SqlDatabase{
:classname "org.h2.Driver"
:subprotocol "h2"
:subname "mem:test_db"
:user "test"
:password ""}
The ragtime.core/connection
multimethod is a way of creating a database from a URL. It dispatches off the URL scheme, so if the URL was "jdbc:h2:mem:test_db", it would dispatch off "jdbc".
The ragtime.sql library includes an implementation of the connection
multimethod that handles JDBC URLs like the one above. To use it, require ragtime.sql.database
:
(use 'ragtime.core)
(require 'ragtime.sql.database)
(connection "jdbc:h2:mem:test_db")
;; The above line is equivalent to the previous SqlDatabase example