25

Is there a way to automatically do a rake db:migrate RAILS_ENV=test after each rake db:migrate when in development environment?

I have guard and guard-rspec running, and I am really annoyed about the failing tests, even if it works manually in the browser.

It costs me at least 15 minutes every time I had a pause from development, to figure out that I simply forgot to call rake db:migrate:test after the change of the database.

Since I am already using guard I thought about adding guard-rake to the project also, but I dont know which file I should watch. When watching development.sqlite3, rake db:migrate RAILS_ENV=test would be fired every time I do something with my records through the browser, so this is not really what I want.

Can someone help me with my problem?

NobbZ
  • 1,360
  • 3
  • 15
  • 30

7 Answers7

20

Possibly just make a command alias in your .bashrc file.

~/.bashrc

alias rake_db_migrate='rake db:migrate db:test:prepare'

Terminal

$ rake_db_migrate
Daniel Doezema
  • 1,592
  • 10
  • 13
  • Args... Yes, simple as this... I leave the question open for a while. I hope that there will be a more ruby or rails way to do this. – NobbZ Aug 03 '11 at 17:03
  • Also I use `alias rake_db_migrate='rake db:migrate && rake db:migrate:test'`, so test-db is only migrated when the migration of the other one is succesfull – NobbZ Aug 03 '11 at 17:09
  • @NobbZ - Good call, added to my answer. – Daniel Doezema Aug 03 '11 at 17:51
  • 1
    I was slaped by far to less sleep... Since there is no `db:migrate:test` task command line must be `alias rake_db_migrate='rake db:migrate && rake db:migrate RAILS_ENV=test'`. Already edited the answer, waiting for approval. – NobbZ Aug 03 '11 at 21:14
  • @ninja08 Care to elaborate on your solution? – Noz Aug 25 '14 at 23:49
  • You can possibly make your own rake task to do both if you want a more ruby way. – CleoR Apr 27 '15 at 17:36
  • @CleoR: I'd personally have to say this is a "6 of one, half a dozen of the other" situation -- but yes that could be done. One would need to a add a new file in `lib/tasks/db.rake` and then `enhance` the `db:migrate` task to invoke the `db:test:prepare` task. One major issue I can see is that we've introduced unexpected behavior into the project that would affect everyone working on the project. – Daniel Doezema Apr 27 '15 at 20:17
  • @DanielDoezema I like the alias solution the best, thats what I ultimately ended up doing. But if one did want a ruby way to accomplish this, you could create a new rake task (so you don't introduce unexpected behavior for everyone else) and then call the other rake tasks from within that rake task with syntax like this. 'Rake::Task["db:migrate"].invoke' – CleoR Apr 27 '15 at 21:37
  • 1
    I didn't bother to read the other posts until now, but other people suggested it already. – CleoR Apr 27 '15 at 21:38
4

I use this alias:
alias rake_db_migrate='rake db:migrate && rake db:migrate RAILS_ENV=test'

because rake db:test:prepare is deprecated.

The reason why I use this is because our project uses pg_search (postgreSQL) along with the structure.sql (not schema.rb) and for some reason running rake db:migrate does not prepare the test database.

echo
  • 900
  • 1
  • 9
  • 17
3

I prefer to use an alias this way:

In your ~/.bashrc

alias migrate='rake db:migrate && rake db:test:prepare'

Its easy to spend 30 minutes trying to figure why your tests are not passing only to remember you didn't reset the database. This will solve that problem.

fontno
  • 6,642
  • 6
  • 36
  • 43
  • See @Dorian's answer for a version of this that only invokes rake once by chaining tasks `alias migrate='rake db:migrate db:test:prepare'` http://stackoverflow.com/a/19503069/67834 – Eliot Sykes Sep 29 '14 at 09:08
2

Faster: alias migrate='rake db:migrate db:test:prepare' (add this in your .bashrc, it will load Rails only one time)

Dorian
  • 22,759
  • 8
  • 120
  • 116
2

An option which I quite like is to override the actual task in another rake script. This will be invoked automatically after running the migration. Like this I always create an ERD diagram after I migrate the database:

# lib/tasks/database.rake
namespace :db do
  desc 'Additional migrate task that creates the diagram'
  task :migrate do
    if Rails.env.development?
      Rake::Task['diagram:erd'].invoke
    end
  end
end

So in your case:

# lib/tasks/database.rake
namespace :db do
  desc 'Additional migrate task that creates the diagram'
  task :migrate do
    `rake db:migrate RAILS_ENV=test`
  end
end

Another approach would be to run the following, which clones your new schema to the test database:

rake db:migrate db:test:clone
Besi
  • 22,579
  • 24
  • 131
  • 223
  • 1
    Good question. They reside in `lib/tasks/database.rake` in my case and they will be dynamically loaded from there. I've updated my question accordingly. – Besi Oct 07 '14 at 14:59
0

In response to your original question of using guard-rake, you could watch db/schema.rb, as this will be updated whenever you migrate the database. However, this file will also be changed if you do a rollback, so you would likely have to pull out the migration version from the schema definition line in db/schma.rb or use rake db:test:prepare instead of rake db:migrate RAILS_ENV=test.

It seems like this is brittle, so using a shell alias is probably the better approach. I just wish there was a better way!

Michael Herold
  • 1,292
  • 1
  • 13
  • 22
0

If you feel like having this as a one-liner that just works, you can have it as:

echo "alias rake-migrate='rake db:migrate && rake db:migrate RAILS_ENV=test'" >> ~/.zshrc && source ~/.zshrc

and for the rollback there is:

echo "alias rake-rollback='rake db:rollback && rake db:rollback RAILS_ENV=test'" >> ~/.zshrc && source ~/.zshrc

then, just run in the terminal

rake-migrate

or

rake-rollback

note: this will add an alias to the ~/.zshrc file. note 2:: if you do this, say terminal1, and use another terminal tab, or vscode terminal, then just run source ~/.zshrc on the terminal you want to run it

nabais
  • 1,981
  • 1
  • 12
  • 18