# Original file by Tobias Luetke, found on # http://blog.leetsoft.com/2006/5/29/easy-migration-between-databases # # set_sequences task by tnb@thenakedbrain.com # namespace :db do namespace :backup do def entity_table?(table_name) columns = ActiveRecord::Base.connection.columns(table_name).map { |column| column.name } columns.include?('id') || columns.include?('party_id') end def interesting_tables tables = ActiveRecord::Base.connection.tables.sort.reject do |tbl| ['schema_info', 'sessions', 'logged_exceptions'].include?(tbl) end tables.select do |tbl| entity_table?(tbl) end end def load_table tbl, loaded_tables return if loaded_tables.include? tbl loaded_tables << tbl klass = tbl.classify.constantize klass.foreign_keys.each do |f_key| load_table f_key.references_table_name, loaded_tables end ActiveRecord::Base.transaction do puts "Loading #{tbl}..." if ActiveRecord::Base.connection.adapter_name.downcase == 'postgresql' ActiveRecord::Base.connection.execute "ALTER TABLE #{tbl} DISABLE TRIGGER ALL" elsif ActiveRecord::Base.connection.adapter_name.downcase == 'mysql' ActiveRecord::Base.connection.execute "SET FOREIGN_KEY_CHECKS=0" end YAML.load_file("#{tbl}.yml").each do |fixture| entity = klass.new(fixture) entity.id = fixture['id'] entity.save_without_validation! if fixture.keys.include?('position') && entity.position != fixture['position'].to_i puts "Adjusting position #{entity.position} => #{fixture['position']}" entity.position = fixture['position'] entity.save_without_validation! end klass.find(fixture['id']) end if ActiveRecord::Base.connection.adapter_name.downcase == "postgresql" ActiveRecord::Base.connection.execute "ALTER TABLE #{tbl} ENABLE TRIGGER ALL" elsif ActiveRecord::Base.connection.adapter_name.downcase == 'mysql' ActiveRecord::Base.connection.execute "SET FOREIGN_KEY_CHECKS=1" end end end desc "Dump entire db." task :write => :environment do dir = Rails.root + "/db/backup" FileUtils.mkdir_p(dir) FileUtils.chdir(dir) interesting_tables.each do |tbl| klass = tbl.classify.constantize puts "Writing #{tbl}..." entities = klass.find(:all) if klass.column_names.include? 'type' entities = entities.select { |e| e.type == klass } end File.open("#{tbl}.yml", 'w+') { |f| YAML.dump entities.collect(&:attributes), f } end end task :read => [:environment, 'db:schema:load'] do dir = Rails.root + '/db/backup' FileUtils.mkdir_p(dir) FileUtils.chdir(dir) loaded_tables = [] interesting_tables.each do |tbl| load_table(tbl, loaded_tables) end end desc "Set postgresql sequence currval to highest id for each table" task :set_sequences => :environment do if ActiveRecord::Base.connection.adapter_name.downcase == "postgresql" interesting_tables.each do |tbl| if ActiveRecord::Base.connection.columns(tbl).map { |column| column.name }.include?('id') puts "Setting sequence's currval to highest id for #{tbl}" ActiveRecord::Base.connection.execute "select setval('#{tbl}_id_seq', (select max(id) from #{tbl}));" end end else puts "This operation only works for postgresql databases." end end end end