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

On Fri, Sep 12, 2008 at 1:02 AM, Adam [email protected] wrote:

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?

% 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 (Google Code Archive - Long-term storage for Google Code Project Hosting.):

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
=============================================
– create_table(:product_messages)
-> 0.7646s
-> 0 rows
– create_table(:products_product_messages)
-> 0.0913s
-> 0 rows
== AddProductMessages: migrated (0.8575s)
====================================

voila!

Adam wrote:

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