Skip to content

Commit

Permalink
Add rake :with_data tasks status, version, forward, abort_if_pending_…
Browse files Browse the repository at this point in the history
…migrations
  • Loading branch information
Andrew J Vargo committed Apr 16, 2011
1 parent efecad3 commit 4077abc
Show file tree
Hide file tree
Showing 2 changed files with 146 additions and 9 deletions.
12 changes: 12 additions & 0 deletions lib/data_migrator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,15 @@ def migrations_path
end
end
end

module ActiveRecord
class MigrationProxy
def is_data?
!(self.filename =~ /db\/data\//).nil?
end

def is_schema?
!(self.filename =~ /db\/migrate\//).nil?
end
end
end
143 changes: 134 additions & 9 deletions lib/tasks/databases.rake
Original file line number Diff line number Diff line change
@@ -1,5 +1,107 @@
require 'data_migrator'

namespace :db do


namespace :migrate do
namespace :status do
desc "Display status of data and schema migrations"
task :with_data => :environment do
config = ActiveRecord::Base.configurations[Rails.env || 'development']
ActiveRecord::Base.establish_connection(config)
unless ActiveRecord::Base.connection.table_exists?(DataMigration::DataMigrator.schema_migrations_table_name)
puts 'Data migrations table does not exist yet.'
next # means "return" for rake task
end
unless ActiveRecord::Base.connection.table_exists?(ActiveRecord::Migrator.schema_migrations_table_name)
puts 'Schema migrations table does not exist yet.'
next # means "return" for rake task
end

db_list_data = ActiveRecord::Base.connection.select_values("SELECT version FROM #{DataMigration::DataMigrator.schema_migrations_table_name}")
db_list_schema = ActiveRecord::Base.connection.select_values("SELECT version FROM #{ActiveRecord::Migrator.schema_migrations_table_name}")
file_list = []

Dir.foreach(File.join(Rails.root, 'db', 'data')) do |file|
# only files matching "20091231235959_some_name.rb" pattern
if match_data = /(\d{14})_(.+)\.rb/.match(file)
status = db_list_data.delete(match_data[1]) ? 'up' : 'down'
file_list << [status, match_data[1], match_data[2], 'data']
end
end

Dir.foreach(File.join(Rails.root, 'db', 'migrate')) do |file|
# only files matching "20091231235959_some_name.rb" pattern
if match_data = /(\d{14})_(.+)\.rb/.match(file)
status = db_list_schema.delete(match_data[1]) ? 'up' : 'down'
file_list << [status, match_data[1], match_data[2], 'schema']
end
end

file_list.sort!{|a,b| "#{a[1]}_#{a[4] == 'data' ? 1 : 0}" <=> "#{b[1]}_#{b[4] == 'data' ? 1 : 0}" }

# output
puts "\ndatabase: #{config['database']}\n\n"
puts "#{"Status".center(8)} #{"Type".center(8)} #{"Migration ID".ljust(14)} Migration Name"
puts "-" * 60
file_list.each do |file|
puts "#{file[0].center(8)} #{file[3].center(8)} #{file[1].ljust(14)} #{file[2].humanize}"
end
db_list_schema.each do |version|
puts "#{'up'.center(8)} #{version.ljust(14)} *** NO SCHEMA FILE ***"
end
db_list_data.each do |version|
puts "#{'up'.center(8)} #{version.ljust(14)} *** NO DATA FILE ***"
end
puts
end
end
end # END OF MIGRATE NAME SPACE

namespace :forward do
desc 'Pushes the schema to the next version (specify steps w/ STEP=n).'
task :with_data => :environment do
# TODO: No worky for .forward
step = ENV['STEP'] ? ENV['STEP'].to_i : 1
# DataMigration::DataMigrator.forward('db/data/', step)
migrations = pending_migrations.reverse.pop(step).reverse
migrations.each do | pending_migration |
if pending_migration.is_data?
DataMigration::DataMigrator.run(:up, "db/data/", pending_migration.version)
elsif pending_migration.is_schema?
ActiveRecord::Migrator.run(:up, "db/migrate/", pending_migration.version)
end
end
end
end

namespace :version do
desc "Retrieves the current schema version number"
task :with_data => :environment do
puts "Current version: #{[DataMigration::DataMigrator.current_version, ActiveRecord::Migrator.current_version].max}"
end
end

namespace :abort_if_pending_migrations do
desc "Raises an error if there are pending migrations"
task :with_data => :environment do
if defined? ActiveRecord
if pending_data_migrations.any? || pending_schema_migrations.any?
puts "You have #{pending_schema_migrations.size} pending schema migrations:"
pending_schema_migrations.each do |pending_migration|
puts ' %4d %s' % [pending_migration.version, pending_migration.name]
end
puts "You have #{pending_data_migrations.size} pending data migrations:"
pending_data_migrations.each do |pending_migration|
puts ' %4d %s' % [pending_migration.version, pending_migration.name]
end
abort %{Run "rake data:migrate:with_data" to update your database then try again.}
end
end
end
end
end

namespace :data do
task :load_config => :rails_env do
require 'active_record'
Expand Down Expand Up @@ -37,12 +139,12 @@ namespace :data do
DataMigration::DataMigrator.run(:down, "db/data/", version)
end

desc "Display status of migrations"
desc "Display status of data migrations"
task :status => :environment do
config = ActiveRecord::Base.configurations[Rails.env || 'development']
ActiveRecord::Base.establish_connection(config)
unless ActiveRecord::Base.connection.table_exists?(DataMigration::DataMigrator.schema_migrations_table_name)
puts 'Schema migrations table does not exist yet.'
puts 'Data migrations table does not exist yet.'
next # means "return" for rake task
end
db_list = ActiveRecord::Base.connection.select_values("SELECT version FROM #{DataMigration::DataMigrator.schema_migrations_table_name}")
Expand Down Expand Up @@ -76,28 +178,51 @@ namespace :data do

desc 'Pushes the schema to the next version (specify steps w/ STEP=n).'
task :forward => :environment do
# TODO: No worky
# TODO: No worky for .forward
step = ENV['STEP'] ? ENV['STEP'].to_i : 1
DataMigration::DataMigrator.forward('db/data/', step)
# DataMigration::DataMigrator.forward('db/data/', step)
migrations = pending_data_migrations.reverse.pop(step).reverse
migrations.each do | pending_migration |
DataMigration::DataMigrator.run(:up, "db/data/", pending_migration.version)
end
end

desc "Retrieves the current schema version number"
task :version => :environment do
puts "Current version: #{DataMigration::DataMigrator.current_version}"
puts "Current data version: #{DataMigration::DataMigrator.current_version}"
end

desc "Raises an error if there are pending migrations"
task :abort_if_pending_migrations => :environment do
if defined? ActiveRecord
pending_migrations = DataMigration::DataMigrator.new(:up, 'db/data').pending_migrations

if pending_migrations.any?
if pending_data_migrations.any?
puts "You have #{pending_migrations.size} pending migrations:"
pending_migrations.each do |pending_migration|
pending_data_migrations.each do |pending_migration|
puts ' %4d %s' % [pending_migration.version, pending_migration.name]
end
abort %{Run "rake data:migrate" to update your database then try again.}
end
end
end
end

def pending_migrations
sort_migrations pending_data_migrations, pending_schema_migrations
end

def pending_data_migrations
DataMigration::DataMigrator.new(:up, 'db/data').pending_migrations
end

def pending_schema_migrations
ActiveRecord::Migrator.new(:up, 'db/migrate').pending_migrations
end

def sort_migrations set_1, set_2=nil
migrations = set_1 + (set_2 || [])
migrations.sort{|a,b| sort_string(a) <=> sort_string(b)}
end

def sort_string migration
"#{migration.version}_#{migration.is_data? ? 1 : 0}"
end

0 comments on commit 4077abc

Please sign in to comment.