When you work with rails, and run say db:schema:dump
or db:structure:dump
from Rake it will write out the state of your development DB into the schema files. When we run the tests, db:test:prepare
also copies the current state of the development database - which makes sense, to a degree, because you are probably working on a feature that needs database tweaks for the current branch.
However, we often need to reset the development database to the state that can be achieved by performing all the migrations in sequence, and then reset the testing database to conform to that - and then write out the schema/structure that can be committed to the source tree for the production branch. Currently, we do this with this monstrosity of a shell command:
bundle exec rake db:drop && bundle exec rake db:create && \
bundle exec rake log db:migrate > /tmp/miglog.log && \
bundle exec rake db:schema:dump && \
RAILS_ENV=test bundle exec rake db:drop && \
RAILS_ENV=test bundle exec rake db:create && bundle exec rake
db:test:prepare
This looks horrible, is absolutely unreadable and also very slow because every invocation here boots the Rails env afresh.
Here's what I was wondering: could we remove some steps from this command? And could we fold these into a handwritten Rake task? I presume that would be difficult because the Rails environment gets configured differently depending on RAILS_ENV
, but would love to at least remove the Rails env reloading.
You could simplify this to
bundle exec rake db:migrate:reset
bundle exec rake db:test:prepare
The reset task runs drop, create, migrate. Running migrations dumps the schema anyway (unless you've changed dump_schema_after_migration
to false)
The test:prepare
step as you know, dumps and loads the schema, and also does a purge (depends slightly on database adapter but basically drops and recreates the database). Given that you have already just dumped the schema, you could change this to
bundle exec rake db:migrate:reset
bundle exec rake db:test:load_schema
Lastly, the tasks in db:test largely know that they should only run against the test database - regardless of rails env they use the test database when needed, so you could just do
bundle exec rake db:migrate:reset db:test:load_schema
Lastly, there are some who would also tell you that running migrations from scratch is heresy and that the definitive source of truth is schema.rb (as generated by your production environment)