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