After running 'down' some migrations using 'rake db:migrate:down', I am
unable to performs any tests. The message received is:
You have 3 pending migrations:
1. blah
2. blahblah
3. blahblahblah
Run "rake db:migrate" to update your database then try again.
How can I remove (undo) migrations and run tests?
Interestingly, 'similar actions' are working on a different machine. I
remember having the same problem and it disappeared after I experimented
few things with rake:db:migrate. Is there any procedure for removing
migrations?
That's an unusual question. The reason you have tests is to verify
your code actually does what you think it's doing. If you migrate
down, you add and/or remove model attributes, which (hopefully) your
code depends on. And your tests should fail if you change that. That
is, if your code doesn't break just trying to run the tests.
Are your trying to run a prior version of your app? If so, you should
use your revision control system to pull down an older copy of the
code and db:reset.
Well, I need to remove some database tables from my application. So I am
using rake db:migrate:down to undo/remove migrations. Also, I have
changed (added/removed/modified) the code in model, view, controller,
and tests to make these changes. Now I need to run tests in order to
check everything is working.
I can pull out an old copy from revision control system. But, what if
migrations that need to be removed are not the latest ones. Lets assume
that there are 30
migrations.
- migration # 15 and 17 - are related to adding new tables
- migration # 22 and 25 - add column to above tables.
So I need to remove/undo migrations 15, 17, 22, and 25. I need other
migrations as they are not related to these tables. What should I do in
such situation?
I did db:migrate:down for above migrations and also made necessary
changes in the code and now trying to run tests. Am I following wrong
approach?
I see. Ok, I see a couple of options here. Some of which have been
suggested already.
1. Rip out (svn remove) the migrations you don't want. Reset the db.
2. Add new migrations to add/fix/remove the changes.
3. db:migrate down to the lowest possible version, comment out the the
guts of the migrations you don't want. Then migrate back up.
4. Something entirely different that I can't think of right now:)
Which approach you should take depends on a couple of factors ... such
as ... whether the app is in production yet, how much code and tests
are affected, how true to the "rails way" you want to stay ... things
like that.
But then what is the purpose of db:migrate:down (and self.down method in
migration file)? The method self.down does roll back any changes if
needed, but its effects are not reflected in other areas such as 'rake
test'.
I am probably going to do 'rake db:migrate:down' and then 'svn remove'
for the particular migration file.
But then what is the purpose of db:migrate:down (and self.down method in
migration file)? The method self.down does roll back any changes if
needed, but its effects are not reflected in other areas such as 'rake
test'.
Migrations really shouldn't be thought of as "choose 4 items from part A
of the menu".
If you need to make adjustments to your schema, you either rollback to a
previous version of the schema earlier than what you want to undo and
edit those migrations (each self.down should undo its self.up), or you
create new migrations to remove what you don't want/need anymore (the
self.down should put back what self.up removes).
The strength of the serial migrations is that you can migrate to the
state of the schema at any point in time.
Riddle me this Batman:
If you undo just migrations 15, 17, 22, 25, and later add a new
migration 33, what do you expect would happen when you rake db:migrate
again?
I suspect that your pending migrations are migration files (like
017_add_x.rb) that aren't referenced in the schema_migrations table.
But then what is the purpose of db:migrate:down (and self.down method in migration file)?
On a deployed database, the only direction should be up. If you deploy a new version, and encounter an emergency, the cap rollback feature cannot roll your database back. If the current code no longer likes the database, you could then use db:migrate:down, iff it is fully tested, and it won't erase any live data.
However, once you deploy, if you rethink a feature, and want less database fields, you should write a progressive migration that removes those fields in its .up method. Its .down method, if any, should put the fields back in.
Because you should not write proactive code into a .down method without immediately testing it, you generally should not write anything in a .down method when you create a new migration. Do not, for example, write a .down method because you think you must (or because an Official Style Guideline told you to) and then not test it. A colleague might run it, thinking it's tested, and get a nasty surprise. Worse, that could be you!
The major benefit of the .down method derives from a problem with unit tests and their fixtures. Unit tests should cover every line of your Rails project - /except/ the lines in your historical migrations! At migration time, your tests might dislike the new version. You can build a .down method, then fix the tests while alternately calling down and up on the migration.