diff options
author | David Heinemeier Hansson <david@loudthinking.com> | 2005-03-01 14:27:32 +0000 |
---|---|---|
committer | David Heinemeier Hansson <david@loudthinking.com> | 2005-03-01 14:27:32 +0000 |
commit | eac7cf0b0608132673220d9045b8ff51dc0804e1 (patch) | |
tree | 770902bf0f248f387520de7312f6db9a3cf8f504 /activerecord/lib/active_record/migration.rb | |
parent | 28a11969ced52abf3d7d51f486779cf31d1efe1f (diff) | |
download | rails-eac7cf0b0608132673220d9045b8ff51dc0804e1.tar.gz rails-eac7cf0b0608132673220d9045b8ff51dc0804e1.tar.bz2 rails-eac7cf0b0608132673220d9045b8ff51dc0804e1.zip |
Added preliminary support for an agile database migration technique (currently only for MySQL)
git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@818 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
Diffstat (limited to 'activerecord/lib/active_record/migration.rb')
-rw-r--r-- | activerecord/lib/active_record/migration.rb | 94 |
1 files changed, 94 insertions, 0 deletions
diff --git a/activerecord/lib/active_record/migration.rb b/activerecord/lib/active_record/migration.rb new file mode 100644 index 0000000000..8734a0831e --- /dev/null +++ b/activerecord/lib/active_record/migration.rb @@ -0,0 +1,94 @@ +module ActiveRecord + class IrreversibleMigration < ActiveRecordError + end + + class Migration + class << self + def up() end + def down() end + + private + def method_missing(method, *arguments, &block) + ActiveRecord::Base.connection.send(method, *arguments, &block) + end + end + end + + class Migrator + class << self + def up(migrations_path, target_version = nil) + new(:up, migrations_path, target_version).migrate + end + + def down(migrations_path, target_version = nil) + new(:down, migrations_path, target_version).migrate + end + + def current_version + Base.connection.select_one("SELECT version FROM schema_info")["version"].to_i + end + end + + def initialize(direction, migrations_path, target_version = nil) + @direction, @migrations_path, @target_version = direction, migrations_path, target_version + end + + def current_version + self.class.current_version + end + + def migrate + migration_classes do |version, migration_class| + Base.logger.info("Reached target version: #{@target_version}") and break if reached_target_version?(version) + next if irrelevant_migration?(version) + + Base.logger.info "Migrating to #{migration_class} (#{version})" + migration_class.send(@direction) + + set_schema_version(version) + end + end + + private + def migration_classes + for migration_file in migration_files + load(migration_file) + version, name = migration_version_and_name(migration_file) + yield version, migration_class(name) + end + end + + def migration_files + files = Dir["#{@migrations_path}/[0-9]*_*.rb"] + down? ? files.reverse : files + end + + def migration_class(migration_name) + migration_name.camelize.constantize + end + + def migration_version_and_name(migration_file) + return *migration_file.scan(/([0-9]+)_([_a-z0-9]*).rb/).first + end + + def set_schema_version(version) + Base.connection.update("UPDATE schema_info SET version = #{down? ? version.to_i - 1 : version.to_i}") + end + + def up? + @direction == :up + end + + def down? + @direction == :down + end + + def reached_target_version?(version) + (up? && version.to_i - 1 == @target_version) || (down? && version.to_i == @target_version) + end + + def irrelevant_migration?(version) + (up? && version.to_i <= current_version) || (down? && version.to_i > current_version) + end + end +end
\ No newline at end of file |