Running a specific migration

Hi all,

I'm working on a large rails projects that has a lot of migration
files (around 80). Through some development quirk, probably due to bad
svn merging, my local database hasn't run migration 63. Is there a way
to run this one file without having to roll back through all the later
migrations, which would cause significant data loss?

Many thanks,
Adam

% rake db:migration:up VERSION=63

Christian

Hi Christian,

That rake task didn't work for me. However, I googled "db:migrate:up"
and found the task as part of the easily_migrate plugin. This was
still not what I'm looking for - db:migrate:up just moves the db up
one version, it cannot pick out an arbitrary migration to run. I added
a few of my own tasks to achieve what I wanted - the code is pasted
below if anyone needs it.

Basically I've written three tasks in addition to those from
easily_migrate (http://code.google.com/p/easilymigrate/):

db:specific:up VERSION=X
Sets the database to version X-1, migrates to version X, resets to the
current version

db:specific:down VERSION=X
Sets the database to version X, migrates to version X-1, resets to the
current version

db:specific:redo VERSION=X
Sets the database to version X, migrates to version X-1, migrates back
to version X, resets to the current version

I think these could be quite handy especially if you want to refactor
your old migrations or if you've missed out a column somewhere and
don't want to have to write a whole new migration for it. I hope it's
helpful to someone!

namespace :db do
  namespace :version do
    desc "Manually set the schema version to an arbitrary number, used
to recover from failed migration states. VERSION to be given"
    task :set => :environment do
     # eval "#{model_or_raise}.to_fixture(#{limit_or_nil_string})"
        if ENV['VERSION'].blank?
          raise "No version supplied Current Version:
#{ActiveRecord::Migrator.current_version}. Set VERSION to change
version."
        else
          puts "Current Version:
#{ActiveRecord::Migrator.current_version}\r\n"
          ActiveRecord::Migrator.set_schema_version(ENV['VERSION'])
          puts "New version:
#{ActiveRecord::Migrator.current_version}"
        end
    end
  end

  namespace :migrate do
    desc "Like db:migrate except it automatically targets the next
version up"
    task :up => :environment do
      ActiveRecord::Migrator.migrate("db/
migrate/",ActiveRecord::Migrator.current_version.to_i + 1 )
      puts "New version:
#{ActiveRecord::Migrator.current_version}"
    end

    desc "Like db:migrate except it automatically targets the next
version down"
    task :down => :environment do
      ActiveRecord::Migrator.migrate("db/
migrate/",ActiveRecord::Migrator.current_version.to_i - 1 ) unless
ActiveRecord::Migrator.current_version == 0
      puts "New version:
#{ActiveRecord::Migrator.current_version}"
    end

    namespace :specific do
      desc "Run a specific migration - sets the DB to the version
below and migrates once"
      task :up => :environment do
        if ENV['VERSION'].blank?
          raise "No version supplied Current Version:
#{ActiveRecord::Migrator.current_version}. Set VERSION to change
version."
        else
          current_version = ActiveRecord::Migrator.current_version
          puts "Current Version: #{current_version}\r\n"

ActiveRecord::Migrator.set_schema_version(ENV['VERSION'].to_i - 1)
          puts "Set to version:
#{ActiveRecord::Migrator.current_version}"
          ActiveRecord::Migrator.migrate("db/
migrate/",ActiveRecord::Migrator.current_version.to_i + 1 )
          puts "Migrated to version:
#{ActiveRecord::Migrator.current_version}"
          ActiveRecord::Migrator.set_schema_version(current_version)
          puts "Reset to version:
#{ActiveRecord::Migrator.current_version}"
        end
      end

      desc "Run a specific migration - sets the DB to the version
below and migrates once"
      task :down => :environment do
        if ENV['VERSION'].blank?
          raise "No version supplied Current Version:
#{ActiveRecord::Migrator.current_version}. Set VERSION to change
version."
        else
          current_version = ActiveRecord::Migrator.current_version
          puts "Current Version: #{current_version}\r\n"

ActiveRecord::Migrator.set_schema_version(ENV['VERSION'].to_i)
          puts "Set to version:
#{ActiveRecord::Migrator.current_version}"
          ActiveRecord::Migrator.migrate("db/
migrate/",ActiveRecord::Migrator.current_version.to_i - 1 )
          puts "Migrated to version:
#{ActiveRecord::Migrator.current_version}"
          ActiveRecord::Migrator.set_schema_version(current_version)
          puts "Reset to version:
#{ActiveRecord::Migrator.current_version}"
        end
      end

      desc "Redo a specific migration: run it's down method then it's
up method"
      task :redo => :environment do
        if ENV['VERSION'].blank?
          raise "No version supplied Current Version:
#{ActiveRecord::Migrator.current_version}. Set VERSION to change
version."
        else
          current_version = ActiveRecord::Migrator.current_version
          puts "Current Version: #{current_version}\r\n"

ActiveRecord::Migrator.set_schema_version(ENV['VERSION'].to_i)
          puts "Set to version:
#{ActiveRecord::Migrator.current_version}"
          ActiveRecord::Migrator.migrate("db/
migrate/",ActiveRecord::Migrator.current_version.to_i - 1 )
          puts "Migrated to version:
#{ActiveRecord::Migrator.current_version}"
          ActiveRecord::Migrator.migrate("db/
migrate/",ActiveRecord::Migrator.current_version.to_i + 1)
          puts "Migrated to version:
#{ActiveRecord::Migrator.current_version}"
          ActiveRecord::Migrator.set_schema_version(current_version)
          puts "Reset to version:
#{ActiveRecord::Migrator.current_version}"
        end
      end
    end
  end
end

script/console

require 'db/migrate/20090418023701_add_product_messages.rb'

=> ["AddProductMessages"]

AddProductMessages.up

== AddProductMessages: migrating