Reputation: 800
I'm new to Ruby on Rails, I know things but now I have to face real projects and do things. I wrote this migration:
def change
change_table :societies do |t|
## Database authenticatable
t.string :email, :null => false, :default => ""
t.string :encrypted_password, :null => false, :default => ""
## Recoverable
t.string :reset_password_token
t.datetime :reset_password_sent_at
## Rememberable
t.datetime :remember_created_at
## Trackable
t.integer :sign_in_count, :default => 0
t.datetime :current_sign_in_at
t.datetime :last_sign_in_at
t.string :current_sign_in_ip
t.string :last_sign_in_ip
# Token authenticatable
t.string :authentication_token
And when I tried to roll it back I get ActiveRecord::IrreversibleMigration I know where is the mistake and my question is:
Can I just change an applied migration to fix what is wrong and then re-run rake db:migrate?
O do I have to modify the migration with up/down methods, revert the migration and then migrate again?
Or maybe I shoud drop the table with a new migration and re-create it? Which is the best practice?
Upvotes: 2
Views: 724
Reputation: 53349
TL;DR:
Full answer:
If you haven't pushed anything to the remote/central repository yet, you can do whatever you want with respect to your new changes, since it only affects you. Just change the database and migration files to suit your needs. And in fact, it's best practice to change the migration files here rather than cluttering the source base with unnecessary migrations.
If you have pushed to remote but you know for certain that nobody else has pulled from that branch yet (if for example, you are the only user of that branch, or if it's a small team and you've communicated with all members), again you can do whatever you want with the recent changes, including migrations.
Now, if someone else has pulled, but the change is not live yet, you can still usually do whatever you want if the team is not too large. Just be aware that your changing an already-committed migration file could cause another developer an annoying development environment re-bootstrap if they're not aware of what you're doing, so tell them exactly what they need to do to get their dev environment back in sync. So just communicate clearly with the rest of the team in this case.
Finally, what if the migration has already been pulled into production and run (or if the development team is too large to efficiently coordinate changing migrations with the other devs)? In this case, it's usually better to write a new migration to reverse the errant one. There are rare cases where a good cowboy programmer can get away with manually editing already-run migrations in production (and where that might even be a good idea), but you have to be very careful in that case because you're playing with fire (and have an easy revert mechanism if you screw up).
In any case, if you're testing thoroughly, it should be very rare for a bad migration to make it all the way to production. It should be unusual for a bad migration to even make it to the central repository (in any branch that more than one dev is working on, that is).
With that out of the way, let's say following the above guidelines you've already decided it's okay to change your migrations. Then, to answer your specific questions:
Can I just change an applied migration to fix what is wrong and then re-run rake db:migrate?
No, once a migration has been run, its id is stored in the database, and it won't be run again even if the file changes.
Or do I have to modify the migration with up/down methods, revert the migration and then migrate again?
You should modify the migration with up/down methods, yes. But as you already said, you can't revert the migration the official way. Instead you can either re-bootstrap your environment from an empty slate, or you can manually revert the migration using a sql queries (remember to also remove the associated id from the migrations table). Then, re-run the migration.
Or maybe I shoud drop the table with a new migration and re-create it?
Don't do this unless you are forced to (and even then be careful that when running it in production you don't inadvertently kill data during this process!).
Finally, it should be noted that if the only change you're making to the migration file is splitting a "change" into "up/down" methods, and the "up" part is exactly the same after your modification, you can even get away with skirting the above guidelines a bit because it won't hurt other developers (they can now just rollback something they couldn't have rolled back before). But err on the side of caution in that case -- you don't want to screw up and accidentally change the up method here even slightly.
Upvotes: 4
Reputation: 5363
You can't use change with change table. So you will need a up and down method. Check http://guides.rubyonrails.org/migrations.html for more details but change_table can't be easily reversed so rails can't do it automatically for you. It needs further details on how to do it right.
List of things you can use change with from the above page:
For your last question, I'd suggest adding another migration that reverses your changes if they are already done to the production db or to do it the simple way. If not you could just edit the migration and fix the issues manually but that's more work.
Upvotes: 1
Reputation: 91
According to Rails Migrations Guide:
In general editing existing migrations is not a good idea: you will be creating extra work for yourself and your co-workers and cause major headaches if the existing version of the migration has already been run on production machines. Instead, you should write a new migration that performs the changes you require. Editing a freshly generated migration that has not yet been committed to source control (or, more generally, which has not been propagated beyond your development machine) is relatively harmless
Upvotes: 1