couch-migrate

A simple migration system for CouchDB.

This gem was created because we needed something more than what “rake db:seed” could provide.

Example Migration File

# File: db/migrate/1_name_of_migration.rb
up do
  puts "this will be run when rake executes an 'up'"
end

down do
  puts "this will be run when rake executes a 'down'"
end

Example Migration File Using CouchRest::Model

# File: db/migrate/2_another_migration.rb

# In order to lock model definitions to a point in time (so
# migrations will work in the future even after models change),
# classes can be defined in a migration, that are namespaced
# automatically yet still work with CouchDB's usage of the 'type'
# field. In order to use CouchRest::Models, include this line:
# use_couchrest_model

use_couchrest_model # this must appear before any class definitions

# Defined in app/models/account.rb, but duplicated here without any
# validations or domain logic, in order to lock the model definition
# to this point in time.
class Account < CouchRest::Model::Base
  property :name, String
  property :description, String
  collection_of :things, class_name: Thing
end

class Thing < CouchRest::Model::Base
  belongs_to :account, class_name: Account
  property :name, String
  property :characteristics,     [String]
  timestamps!
  design do
    view :by_name
  end
end

up do
  # an example of limiting whether a migration runs or not. In this
  # case, only run this migration if the CouchDB database is
  # approximately empty.
  begin
    threshold = 5
    db = Account.database # the db url, obtained however you feel
    if db.info['doc_count'] > threshold
      puts "Database (#{db.to_s}) has more than #{threshold} documents. This migration will not run"
      return
    end
  rescue
  end

  Thing.save_design_doc  # you have to manually save the design
                         # document for the view to work.  NOTE:
                         # this will destroy any views not
                         # declared in this file.

  Account.create! do |a|
    a.name = "A new account"

    a.things << Thing.create! do |t|
      t.name = "Thing # 1"
      t.characteristics << "Awesome"
      t.characteristics << "Joy bringing"
      t.hidden = false
    end
    # example code. not tested
  end

end

Example Rake Task

def migrater
  couch_db_url = 'http://127.0.0.1:5984/couch-migrate_test'
  # or, if you are using CouchRest::Model
  # require 'your_couchreset_model_class'
  # couch_db_url = YourCouchRestModelClass.database.to_s
  CouchMigrate::CouchMigrater.new(couch_db_url)
end

namespace :db do
  desc 'migrate all pending migrations'
  task :migrate => ['migrate:up']

  namespace :migrate do
    desc 'couchdb migration up'
    task 'up' => [:environment, :url] do
      migrater.migrate(:up)
    end

    desc 'couchdb migration down'
    task 'down' => [:environment, :url] do
      migrater.migrate(:down)
    end

    desc 'couchdb migration down, then up'
    task 'redo' => [:environment, :url] do
      migrater.migrate(:down)
      migrater.migrate(:up)
    end

    desc 'print couchdb URL'
    task 'url' => :environment do
      $stderr.puts("CouchDB URL: #{CloudProvider.database.to_s}")
    end

  end
end

Note

This gem requires Ruby 1.9 only because of the use of “require_relative”. In the true spirit of open source, if you would like to use this gem with Ruby 1.8, please fork it, fix those requires, enjoy using it, and then submit a pull request. One gold star will be awarded to the person who does this.

Thanks

Thanks to OpenLogic (openlogic.com), a great company that focuses on supporting the Open Source market, for allowing this work to be open sourced.

Contributing to couch-migrate

Copyright © 2011 OpenLogic, Inc. and Greg Edwards. See LICENSE.txt for further details.