Deleting Arbitrary Tables and Migrations from a Rails Application
NOTE: The better answer than using this is to use:
rake db:migrate:down VERSION=20100905201547
which I think should do what my rake task does. I left this post intact, however, because I only found this StackOverflow Post AFTER I wrote it. Sigh. If nothing else, the explanation of how migrations work may help someone.
I do a metric ton of what is called “Greenfield Development” as a solo developer. These two things are what led me to write a Rake task which executes like this:
be rake drop_table_and_migration:go[weathers,20220810081751]
Here’s what that looks like when it runs:
be rake drop_table_and_migration:go[weathers,20220810081751]
Success -- executed query: DROP TABLE weathers
Success -- executed query: DELETE FROM schema_migrations WHERE version = '20220810081751'
Table: weathers dropped and Migration file: 20220810081751 deleted from schema_migrations
You can now modify your schema and re-run your migrations with
bundle exec rake db:migrate
What that does is execute a Rake task which drops a table and deletes a migration entry from the schema_migrations registry.
The way that Rails migrations work is:
- A file named with a timestamp and a migration name is generated.
- The programmer modifies that file and adds the body of the migration.
- The db:migrate command is executed and the database is changed.
- The timestamp of the migration file is inserted into the table schema_migrations
Now there are commands to rollback a migration but they don’t, to my knowledge, allow you to cleanly do an arbitrary timestamp.
Now the reason I referenced both Greenfield Development and working as a solo developer is that this tool isn’t really designed to work in this context. In Greenfield Development, you tend to:
- Constantly develop table structures, try them out
- Realize a field is missing
- Try and rollback. Get it wrong and revert to raw SQL queries in Postgres.
- Modify your migration and then lather / rinse / repeat as needed.
Now you can do it with a command line like the one above.
Here’s the source code. Just add it into your Rails app as a Rake task and enjoy
namespace :drop_table_and_migration do
# be rake drop_table_and_migration:go[weathers,20220810081751]
task :go, [:table, :migration] => :environment do |task, args|
table_name = args[:table]
migration_name = args[:migration]
queries = []
queries << "DROP TABLE #{table_name}"
queries << "DELETE FROM schema_migrations WHERE version = '#{migration_name}'"
queries.each do |query|
begin
ActiveRecord::Base.connection.execute(query)
rescue Exception => e
puts "Hit exception so exiting for safety: #{e.inspect}"
exit
end
puts "Success -- executed query: #{query}"
end
puts "Table: #{table_name} dropped and Migration file: #{migration_name} deleted from schema_migrations"
puts "You can now modify your schema and re-run your migrations with \n\nbundle exec rake db:migrate"
end
end