880cbab435f00197613c9cc2065b4f5a
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
namespace :migrations do
  
  desc 'reverts, renames and re-executes uncommitted migrations that conflict with already committed migrations'
  task :repair => :environment do
    uncommitted = `svn status`.select {|line| line =~ /db\/migrate\//}.collect {|line| line.match(/ db\/migrate\/(.*rb)/)[1]}
    committed   = Dir.glob('db/migrate/*').collect {|line| line.match(/db\/migrate\/(.*rb)/)[1]} - uncommitted
    
    highest_committed   = committed.collect(&:to_i).max
    lowest_uncommitted  = uncommitted.collect(&:to_i).min
    
    schema_version = ActiveRecord::Base.connection.select_one("select version from schema_info")["version"].to_i
    
    # revert uncommitted migrations
    uncommitted.sort_by(&:to_i).reverse.each do |migration|
      version = migration.to_i
      if version <= schema_version
        name = migration.match(/(\d*_.*).rb/)[1]
        class_name = (require 'db/migrate/' + name)[0]
        puts class_name.constantize.down 
      end
    end
    
    #set it back to the version prior to all the uncommitted migrations - this doesn't get done automatically by calling down
    ActiveRecord::Base.connection.execute("update schema_info set version=#{schema_version-1}")
    
    version_offset = (highest_committed - lowest_uncommitted) + 1
    
    uncommitted.each do |old_name|
      version  = old_name.to_i + version_offset
      new_name = version.to_s.rjust(3,'0') + old_name.gsub(/\d/, '')
      `mv db/migrate/#{old_name} db/migrate/#{new_name}`
    end
    
    puts "Uncommited migrations have been reversed and renamed. You can now migrate."
  end
end

Refactorings

No refactoring yet !

Bfec5f7d1a4aaafc5a2451be8c42d26a

macournoyer

October 29, 2007, October 29, 2007 20:57, permalink

No rating. Login to rate!

This is the most useful rake task ever for a Rails user!
A couple of changes:
* rename to db:migrate:repair
* fix version on line 24 if more then one uncommitted migration
* invoke db:migrate at the end

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
namespace :db do
  namespace :migrate do
    desc 'Reverts, renames and re-executes uncommitted migrations that conflict with already committed migrations'
    task :repair => :environment do
      uncommitted = `svn status`.select {|line| line =~ /db\/migrate\//}.collect {|line| line.match(/ db\/migrate\/(.*rb)/)[1]}
      committed   = Dir.glob('db/migrate/*').collect {|line| line.match(/db\/migrate\/(.*rb)/)[1]} - uncommitted
    
      highest_committed   = committed.collect(&:to_i).max
      lowest_uncommitted  = uncommitted.collect(&:to_i).min
    
      schema_version = ActiveRecord::Base.connection.select_one("SELECT version FROM schema_info")["version"].to_i
    
      # revert uncommitted migrations
      uncommitted.sort_by(&:to_i).reverse.each do |migration|
        version = migration.to_i
        if version <= schema_version
          name = migration.match(/(\d*_.*).rb/)[1]
          class_name = (require 'db/migrate/' + name)[0]
          puts class_name.constantize.down 
        end
      end
    
      # set it back to the version prior to all the uncommitted migrations - this doesn't get done automatically by calling down
      ActiveRecord::Base.connection.execute("UPDATE schema_info SET version = #{schema_version - uncommitted.size}")
    
      version_offset = (highest_committed - lowest_uncommitted) + 1
    
      uncommitted.each do |old_name|
        version  = old_name.to_i + version_offset
        new_name = version.to_s.rjust(3,'0') + old_name.gsub(/\d/, '')
        `mv db/migrate/#{old_name} db/migrate/#{new_name}`
      end
    
      Rake::Task['db:migrate'].invoke
    end
  end
end

Your refactoring





Format Copy from initial code

or Cancel