When I start coding a Ruby on Rails project, I find myself modifying the migration files over and over. I know this is not the way they were intended to use, but to avoid upfront design, I only ad fields when I need them. If I respected the way migrations were intended I would end up with hundred of migrations the first day and I would waste half my day just creating migrations.

After a project is deployed or a second developer is working on it, I revert to the way migrations are intended and I create a new one every time there’s a change I need in the database.

As migrations are intended to run only once, if you modify them, they won’t get run; and if you force them to run them, they’ll fail, because the database already contains such a table. So I’ve found myself doing this quite often:

rake db:drop && rake db:create && rake db:migrate && rake db:seed && rake db:data

db:data is a task I created to generate some sample data. Good known data that I can use to test the site locally. I’m using Factory Girl to create it, which I also use for the tests so I can re-use as much data creating logic as possible. It’s very good to get to a known state of the project you are developing and to get other developers started right away. I really recommend everyone doing it.

The problem is that I also need to reset my test data, so I end up having this other command and it gets horrible:

RAILS_ENV=test rake db:drop && RAILS_ENV=test rake db:create && RAILS_ENV=test rake db:migrate && RAILS_ENV=test rake db:seed

Note: no db:data this time.

I’ve got tired of re-writing these commands or trying to find them in my bash history, so I decided to write a Ruby task that will do it for me and here it is in case you want to use it too:

namespace :db do
  desc "Crush and burn the database"
  task :hard_reset => :environment do
    File.delete("db/schema.rb")
    Rake::Task["db:drop"].execute
    Rake::Task["db:create"].execute
    Rake::Task["db:migrate"].execute
    Rake::Task["db:seed"].execute
    if !Rails.env.test?
      Rake::Task["db:data"].execute
    end
  end

  desc "Generate sample data for developing"
  task :data => :environment do
    # Create the sample data in here
  end
end

Enjoy!

Update: To delete all records without resetting the whole database, check my post Deleting all records in a Rails project.


8 responses to “Really resetting the database”

  1. Khanh Avatar

    The article very wonderful and useful.
    Thanks Pablo

  2. sean behan Avatar

    take a look at yaml_db http://github.com/adamwiggins/yaml_db/ when you’re first starting an app, it’s kind of annoying to create new migrations when you’re still hammering out all the attrs, imo. i usually don’t add migrations on existing models until the first release and even then, it depends on the project and how large the db is.

    yaml_db adds a couple nice tasks
    rake db:data:dump
    rake db:data:load

  3. sean behan Avatar

    btw, great blog!

  4. […] post is inspired by http://pupeno.com/blog/really-resetting-the-database/#comment-1179. But as my blog mostly serves as a reference for my future self, I’d like to reprint this […]

  5. augustin.riedinger Avatar
    augustin.riedinger

    Pretty old article but it seems to work still! How come nobody else has had the issue of merging migration files while developping since ?
    Thanks anyway!

  6. nathanvda Avatar

    You can also just redo the last migration (which is what I need most of the time). Really easy rake db:migrate:redo. An alternative is to rollback migrations, rake db:rollback will rollback one step, or rake db:rollback STEP=x will rollback x migrations. And then just do rake db:migrate again. Much easier.

    1. Codeedog Avatar

      Nathan, your advice is fantastic and did exactly what I needed. Great tip for the db:rollback. I had just one problem, rollback only works if you haven’t modified the migration file already. So, I put it back to the way it was before modification (commented out changes), then did the rollback, then redid the migration with the updated file. Worked like a charm. Better than dropping and redoing the whole shebang.

      Pablo, thanks for the pointers in the OP. Will use that sometime if ever needed.

  7. Gaurav Balodi Avatar
    Gaurav Balodi

    There is another way of using rake tasks. You can do it like this

    RAILS_ENV=test rake db:drop db:create db:migrate db:seed

    Just put the task name with namespace after a space one after the other.

Leave a Reply

You may also like:

Hi, I'm Pablo, this is my web site. You can follow me or connect with me:

Or get new content delivered directly to your inbox.

Join 4,048 other subscribers

I'm writing a book

Stack of copies of How to Hire and Manage Remote Teams

How to Hire and Manage Remote Teams, where I distill all the techniques I've been using to build and manage distributed teams for the past 10 years.

I write about:

announcement blogging book book review book reviews books building Sano Business C# Clojure ClojureScript Common Lisp database Debian Esperanto Git ham radio history idea Java Keep on Posting Kubuntu Lisp Non-Fiction OpenID programming Python Radio Society of Great Britain Rails rant re-frame release Ruby Ruby on Rails Sano science science fiction security self-help Star Trek startups technology Ubuntu web WordPress

I've been writing for a while:

Mastodon

%d bloggers like this: