zabumba
zabumba

Reputation: 12422

rake db:rollback reverting the wrong migration

I am having a problem to revert last migration.

Ever since I installed the 'letrate' gem for rating, any rake db:rollback reverts precisely that letrate gem migration and NOT the last migration as expected.

I doubt this is due to the gem itself.

Any ideas how to fix this, so I can enjoy the very handy rollback?

Same identically issue with:

rake db:migrate:redo

Result:

==  CreateRates: reverting ====================================================
-- drop_table(:rates)
   -> 0.0224s
==  CreateRates: reverted (0.0225s) ===========================================

==  CreateRates: migrating ====================================================
-- create_table(:rates)
NOTICE:  CREATE TABLE will create implicit sequence "rates_id_seq" for serial column "rates.id"
NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "rates_pkey" for table "rates"
   -> 0.1787s
-- add_index(:rates, :rater_id)
   -> 0.0032s
-- add_index(:rates, [:rateable_id, :rateable_type])
   -> 0.0024s
==  CreateRates: migrated (0.1850s) ===========================================

rake db:migrate:status

...
   up     20121205224038  Rename user address column
   up     20121206125016587  ********** NO FILE **********
   up     20121206125016605  ********** NO FILE **********
   up     20121210152550  Create reservations
   up     20121210180233  Create transactions
   up     20121210215840  ********** NO FILE **********
   up     20121218144200  Create videos
   up     20121218144800  Add video to videos
   up     20130108225007  Devise invitable add to users
   up     20130130202046  Acts as taggable on migration
   up     20130205154206  Create commissions
   up     20130207133520  Add user id to event transition

and the files

-rw-r--r--@  1 joel  staff   137 Dec  7 16:40 20121205224038_rename_user_address_column.rb
-rw-r--r--@  1 joel  staff   443 Dec  7 16:40 20121206125016587_create_rating_caches.rb
-rw-r--r--@  1 joel  staff   432 Dec  7 16:40 20121206125016605_create_rates.rb
-rw-r--r--@  1 joel  staff   429 Dec 10 23:30 20121210152550_create_reservations.rb
-rw-r--r--@  1 joel  staff   414 Dec 10 19:03 20121210180233_create_transactions.rb
-rw-r--r--@  1 joel  staff   237 Dec 18 15:44 20121218144200_create_videos.rb
-rw-r--r--@  1 joel  staff   172 Dec 18 16:18 20121218144800_add_video_to_videos.rb
-rw-r--r--@  1 joel  staff   758 Jan  8 23:50 20130108225007_devise_invitable_add_to_users.rb
-rw-r--r--   1 joel  admin   775 Jan 30 21:20 20130130202046_acts_as_taggable_on_migration.rb
-rw-r--r--@  1 joel  admin   422 Feb  5 17:05 20130205154206_create_commissions.rb
-rw-r--r--@  1 joel  admin   266 Feb  7 15:20 20130207133520_add_user_id_to_event_transition.rb

Upvotes: 3

Views: 2155

Answers (1)

deivid
deivid

Reputation: 5268

Ok, the problem is the version number of your letrate migrations. Rails just orders the timestamps in the migration files to know which one was most recently applied. Having 3 more digits in the timestamp, 20121206125016605_create_rates.rb and 20121206125016587_create_rating_caches are always going to be detected as the last migrations.

Let's try to fix it and clean up your migration's status. First rollback the problematic migrations:

rake db:rollback STEP=2

Your rake db:migrate:status now should look like these:

up     20121205224038  Rename user address column
up     20121210152550  Create reservations
up     20121210180233  Create transactions
up     20121210215840  ********** NO FILE **********
up     20121218144200  Create videos
up     20121218144800  Add video to videos
up     20130108225007  Devise invitable add to users
up     20130130202046  Acts as taggable on migration
up     20130205154206  Create commissions
up     20130207133520  Add user id to event transition

Now let's fix their version number (assuming your migrations are in the default db/migrate folder)

mv db/migrate/20121206125016605_create_rates.rb db/migrate/20121206125017_create_rates.rb
mv db/migrate/20121206125016587_create_rating_caches.rb db/migrate/20121206125016_create_rating_caches.rb

Now your db:migrate:status should look like this:

up     20121205224038  Rename user address column
down   20121206125016  Create rating caches
down   20121206125016  Create rates  
up     20121210152550  Create reservations
up     20121210180233  Create transactions
up     20121210215840  ********** NO FILE **********
up     20121218144200  Create videos
up     20121218144800  Add video to videos
up     20130108225007  Devise invitable add to users
up     20130130202046  Acts as taggable on migration
up     20130205154206  Create commissions
up     20130207133520  Add user id to event transition

Now the "timeline" is fixed but we still need to reapply those migrations. rake db:migrate won't work because the last migration is now 20130207133520_add_user_id_to_event_transition.rb and it's been already applied so rake thinks it is up to date... So we have to cheat rake: edit every migration file that appears after 20121206125017_create_rates.rb in the migrate status output by commenting everything inside the down method. If there's only a change method, comment it and create empty up and down methods. So all those down methods will be something like this:

def down
  # This is the old code
  # which I will uncomment later...
end

You also need to create an empty migration because there is a weird migration that has no file associated (the ********** NO FILE ********** one). So create a file named db/migrate/20121210215840_ghost_migration.rb with the following contents:

class GhostMigration < ActiveRecord::Migration
  def up
  end

  def down
  end
end

Now we are ready to simulate rolling all the way back. So do

rake db:rollback STEP=9

The migration status output should now be

up     20121205224038  Rename user address column
down   20121206125016  Create rating caches
down   20121206125016  Create ratings
down   20121210152550  Create reservations
down   20121210180233  Create transactions
down   20121210215840  Ghost migration
down   20121218144200  Create videos
down   20121218144800  Add video to videos
down   20130108225007  Devise invitable add to users
down   20130130202046  Acts as taggable on migration
down   20130205154206  Create commissions
down   20130207133520  Add user id to event transition

Now you can change the files back to their original state by uncommenting what you commented before and remove the "Ghost migration" file. You should actually comment the "up" methods the same way we did with the down methods before, remove the "Ghost migration" file and migrate everything

rake db:migrate

Finally uncomment everything you commented out in the files and things should be running smooth after that (I hope).

Regarding why this happened in the first place, I think this is actually due to the gem itself, which in my opinion should not generate those migrations with invalid (or at least non standard) version numbers. It looks like the gem generates two migrations in the same second so maybe the author added those 3 extra digits to prevent version number collision. I think it would have been better to do everything in the same migration.

I hope this helps you to fix your issue!

UPDATE

Maybe I overcomplicated things. If you don't mind actually rolling back all your migrations and then migrating them up again, you don't need to comment anything on any file (the "Ghost migration" trick would still be necessary though). I just felt it would be safer this way.

Upvotes: 6

Related Questions