module MongoMapper::Migration class MigrationDefinition def upgrade &block if block @upgrade = block else @upgrade end end alias_method :up, :upgrade def downgrade &block if block @downgrade = block else @downgrade end end alias_method :down, :downgrade end class << self def define_migration version, &block version.should! :be_a, Integer definition = MigrationDefinition.new block.call definition migration_definitions[version] = definition end def define_global_migration version, &block version.should! :be_a, Integer definition = MigrationDefinition.new block.call definition global_migration_definitions[version] = definition end def update_global_database_to version puts "Migration for Global Database:" update_database MongoMapper.global_database, global_migration_definitions, version end def update_database_to version puts "Migration for Accounts Databases:" results = {} MongoMapper.accounts_names.each do |account_name| MongoMapper.account_database account_name do |db| result = update_database db, migration_definitions, version results[db.name] = result end end results end def metadata db col = db.collection 'db_metadata' metadata = (col.find_one || {:version => 0}).to_openobject end def global_migration_definitions; @global_migration_definitions ||= [] end def migration_definitions; @migration_definitions ||= [] end protected def increase_db_version migration_definitions, db m = metadata(db) migration = migration_definitions[m.version + 1] raise "No upgrade for version #{m.version + 1}" unless migration and migration.up migration.up.call m.version += 1 update_metadata db, m puts "Database #{db.name} upgraded to version #{m.version}" end def decrease_db_version migration_definitions, db m = metadata(db) migration = migration_definitions[m.version] raise "No downgrade for version #{m.version}" unless migration and migration.down migration.down.call m.version -= 1 update_metadata db, m puts "Database #{db.name} downgraded to version #{m.version}" end def update_database db, migrations, version if metadata(db).version == version puts "Database #{db.name} already is of #{version} version, no migration needed" return false end increase_db_version migrations, db while metadata(db).version < version decrease_db_version migrations, db while metadata(db).version > version true end def update_metadata db, metadata col = db.collection 'db_metadata' col.save metadata.to_hash end def reset [global_migration_definitions, migration_definitions].every.clear end end end