Skip to content

Commit

Permalink
Added MigrationProxy to defer loading of Migration classes until they…
Browse files Browse the repository at this point in the history
… are actually required by the migrator

Signed-off-by: Michael Koziarski <michael@koziarski.com>
[#747 state:resolved]
  • Loading branch information
nikz authored and NZKoz committed Aug 6, 2008
1 parent 29a06f1 commit 0809747
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 6 deletions.
32 changes: 26 additions & 6 deletions activerecord/lib/active_record/migration.rb
Expand Up @@ -349,6 +349,27 @@ def method_missing(method, *arguments, &block)
end
end

# MigrationProxy is used to defer loading of the actual migration classes
# until they are needed
class MigrationProxy

attr_accessor :name, :version, :filename

delegate :migrate, :announce, :write, :to=>:migration

private

def migration
@migration ||= load_migration
end

def load_migration
load(filename)
name.constantize
end

end

class Migrator#:nodoc:
class << self
def migrate(migrations_path, target_version = nil)
Expand Down Expand Up @@ -437,7 +458,7 @@ def migrate
runnable.pop if down? && !target.nil?

runnable.each do |migration|
Base.logger.info "Migrating to #{migration} (#{migration.version})"
Base.logger.info "Migrating to #{migration.name} (#{migration.version})"

# On our way up, we skip migrating the ones we've already migrated
# On our way down, we skip reverting the ones we've never migrated
Expand Down Expand Up @@ -470,11 +491,10 @@ def migrations
raise DuplicateMigrationNameError.new(name.camelize)
end

load(file)

klasses << returning(name.camelize.constantize) do |klass|
class << klass; attr_accessor :version end
klass.version = version
klasses << returning(MigrationProxy.new) do |migration|
migration.name = name.camelize
migration.version = version
migration.filename = file
end
end

Expand Down
20 changes: 20 additions & 0 deletions activerecord/test/cases/migration_test.rb
Expand Up @@ -922,6 +922,26 @@ def test_finds_pending_migrations
migrations[0].name == 'innocent_jointable'
end

def test_only_loads_pending_migrations
# migrate up to 1
ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid", 1)

# now unload the migrations that have been defined
PeopleHaveLastNames.unloadable
ActiveSupport::Dependencies.remove_unloadable_constants!

ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid", nil)

assert !defined? PeopleHaveLastNames

%w(WeNeedReminders, InnocentJointable).each do |migration|
assert defined? migration
end

ensure
load(MIGRATIONS_ROOT + "/valid/1_people_have_last_names.rb")
end

def test_migrator_interleaved_migrations
ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/interleaved/pass_1")

Expand Down

0 comments on commit 0809747

Please sign in to comment.