module Hydra module Migrate class Dispatcher def migrations @migrations || reset! end protected :migrations def reset! @migrations ||= Hash.new { |h,k| h[k] = [] } end def load_migrations(path) Dir[File.join(path,'**','*.rb')].each { |migration_file| existing_migrations = ObjectSpace.each_object(Hydra::Migrate::Migration).to_a load(migration_file) new_migrations = ObjectSpace.each_object(Hydra::Migrate::Migration).to_a - existing_migrations new_migrations.each { |klass| klass.new(self) } } end def define_migration(signature={}, block) self.migrations[signature[:for]] << { :from=>signature[:from].to_s, :to=>signature[:to].to_s, :block=>block } end def migrations_for(target, constraints={}) raise "Not a migratable object: #{target.inspect}" unless target.is_a?(Hydra::ModelMixins::Migratable) if self.migrations.has_key?(target.class) migrations[target.class].select { |v| v[:from].to_s == constraints[:from].to_s and (constraints[:to].nil? or v[:to].to_s == constraints[:to].to_s) } else return [] end end def can_migrate?(object, constraints={}) object.is_a?(Hydra::ModelMixins::Migratable) and not migrations_for(object, {:from=>object.current_migration}.merge(constraints)).empty? end def migrate!(object, to=nil, opts={}) raise "Not a migratable object: #{object.inspect}" unless object.is_a?(Hydra::ModelMixins::Migratable) migrations_for(object, :from=>object.current_migration, :to=>to).each do |migration| migration[:block].call(object, to, self) object.migrationInfo.migrate(migration[:to]) object.current_migration = migration[:to] object.save unless opts[:dry_run] end object end end end end