Faster database resets

18 Dec, 2018
0 views
rails

After I’ve made a significant change to the relationships of the models on the application I’m working on; I wanted to update the seeds file to accommodate new relationships.

Rails’ default command to reset the database rails db:reset drops the database and then recreates all the tables from the schema. Dropping and recreating like this adds some overhead to the command’s run time. I wanted to mitigate that since I didn’t do any schema updates and I just wanted to clear the tables.

It turns out there is a SQL command made precisely for this scenario: TRUNCATE. The only trick is to use the TRUNCATE command with CASCADE to also truncate the tables with foreign key references to the truncated table and RESTART IDENTITY to reset the auto sequences. I also needed to avoid truncating the schema_migrations table which is used in Rails to store which migrations have been run and ar_internal_metadata which stores Active Record’s internal metadata.

Here is the Rake task I’ve ended up with. It usually shaves off ~10s when reseeding the database.

namespace :db do
 desc 'Clears the database and then seeds it'
 task reseed: :environment do 
 Rake::Task["db:truncate"].invoke
 Rake::Task["db:seed"].invoke
 end
 desc 'Clears the database'
 task truncate: :environment do 
 puts "Truncating database"
 ActiveRecord::Base.connection.
 tables.
 reject {|t| t =~ /ar_internal_metadata|schema_migrations/}.
 map do |t|
 putc "."
 command = "TRUNCATE TABLE #{t} RESTART IDENTITY CASCADE"
 ActiveRecord::Base.connection.execute(command)
 end
 puts
 end
end

AltStyle によって変換されたページ (->オリジナル) /