Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save michaeldwan/1287908 to your computer and use it in GitHub Desktop.
Save michaeldwan/1287908 to your computer and use it in GitHub Desktop.
ActiveRecord migrations but like, for mongo
class MongoMigrationGenerator < Rails::Generators::NamedBase
source_root File.expand_path('../templates', __FILE__)
def create_mongo_migration_file
version = Time.now.utc.strftime("%Y%m%d%H%M%S")
template "migration.rb", "db/mongo_migrations/#{version}_#{file_name}.rb"
end
end
class <%= file_name.camelize %> < ::Mongo::Migration
def self.up
end
def self.down
end
end
module Mongo
class Migration
def self.say(message, subitem = false)
puts "#{subitem ? " ->" : "--"} #{message}"
end
end
end
module Mongo
class Migrator
def self.database=(db)
raise "wtf is this? we need a Mongo::DB" unless db.is_a?(Mongo::DB)
@database = db
end
def self.database
unless @database
self.database = MongoMapper.database if defined?(MongoMapper)
end
return @database
end
def self.collection_name
@collection_name ||= "migrations"
end
def self.collection_name=(value)
@collection_name = value
end
def self.migrations_path
@migrations_path ||= Rails.root.join('db', 'mongo_migrations')
end
def self.migrations_path=(value)
@migrations_path = value
end
def self.version_history
database[collection_name].distinct('version')
end
def self.save_history(direction, version)
case direction
when :up then database[collection_name].save(:version => version)
when :down then database[collection_name].remove(:version => version)
end
end
def self.available_migrations
@migrations ||= begin
Dir["#{migrations_path}/*.rb"].map do |migration_file|
MigrationProxy.new(*[File.basename(migration_file).scan(/([0-9]+)_([_a-z0-9]*).rb/).first, migration_file].flatten)
end.sort_by(&:version)
end
end
def self.pending_migrations
history = version_history
available_migrations.reject { |m| history.include?(m.version) }
end
def self.processed_migrations
history = version_history
available_migrations.select { |m| history.include?(m.version) }
end
def self.current_version
version_history.max
end
def initialize(options = {})
@version = options[:version]
@direction = options[:direction] || :up
end
attr_reader :version, :direction
def queue
@queue ||= begin
if version
if direction == :up
[self.class.pending_migrations.detect { |m| m.version == version }]
elsif direction == :down
[self.class.processed_migrations.detect { |m| m.version == version }]
end
elsif direction == :up
self.class.pending_migrations
else
[]
end
end
end
def run!
queue.each do |migration|
migration.run(direction)
self.class.save_history(direction, migration.version)
end
end
class MigrationProxy < Struct.new(:version, :name, :file)
def migration
@instance ||= begin
load(file)
name.camelize.constantize
end
end
def run(direction = :up)
return unless migration.respond_to?(direction)
case direction
when :up then announce "migrating"
when :down then announce "reverting"
end
result = nil
time = Benchmark.measure { result = migration.send("#{direction}") }
case direction
when :up then announce "migrated (%.4fs)" % time.real; puts
when :down then announce "reverted (%.4fs)" % time.real; puts
end
result
end
def announce(message)
text = "#{version} #{name}: #{message}"
length = [0, 75 - text.length].max
puts "== %s %s" % [text, "=" * length]
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment