Rails migration generate - ruby-on-rails

How would one manage if there were a lot of migrations file made using rails g migration?
For example if I had a file that generate a column for a certain table, I had this but again later down the track I wanted to remove this. This type of adding and removing has been repeated quite a bit due to architectural decisions along the way.
I don't like the way I'm creating migrations file for every instance of column (columns) adds and I would like to clean up all my migrations file so they are simple enough.
I understand Migrations are recorded with timestamp with matching file name and in the table to check if they have been already migrated or not. I presume I can delete that specific row in question and also delete the same thing that matches with the file after deleting the column not required.
Is this the best way to go or are there any better examples of this?

It is possible to get rid of migrations to reduce the complexity and ensure that things don't get 'out of sync'.
The simplest way is to generate a new, blank migration file. Copy across the contents of schema.rband then delete all the earlier migrations.
Obviously you would want to ensure that you are using version control (such as Git) and that your database has a backup so you can revert any problems.
I wrote a blog post on the subject here http://www.fmhcc.com.au/ruby/database-migrations-in-rails-and-when-to-start-from-scratch/

Related

Ruby on Rails: Long list of migration files, common?

Is having a long list of migration files often common when building a web application? I seem to be adding up a long list of migration files because I keep forgetting or keep thinking of adding an extra column to a 'already' migrated database table.
Having a long list of migration files is normal. It's one of the best features of rails. Think of them as layers(like an onion) that you stack on top of each other. If you add a new column or table and then you decide that you don't want it anymore you can rollback(peel away) the latest changes. As long as you have the migration files you can move back and forth easily(don't recommend moving much but you get the point). REMEMBER DO NOT DELETE migration files once they are raked unless you do a rollback. When you rollback and delete a migration file make absolutely SURE you are at the right layer(rollback point).
why? because for example when someone clones your app and runs your migration file it goes through all the migration files from beginning to end. if something in the middle is messed up or deleted you won't be able to create the database because it goes through ALL the steps. Hope it helps.
It may be bad habit, but I migrate down using rake db:migrate VERSION=0, then change the respective migration that has (for instance) the users, and finally migrate the database using rake db:migrate. That way i have less of a mess, and know exactly which migration does what to what model. It's cleaner, but I guess this technique can be used only at the beginning of the webapp.
Hope this helps.
One more point to be noted, from rails docs
If you need to create the application database on another system, you should be using db:schema:load, not running all the migrations from scratch. The latter is a flawed and unsustainable approach (the more migrations you'll amass, the slower it'll run and the greater likelihood for issues).
It's strongly recommended to check this file(schema.rb) into your version control system.
IMO, if you do the migrations correctly it should have to have a long list of migrations. Because every little change you have to do via migration. As you said, proper way is to add a new migration when you need to alter a table.
So as I mentioned I believe having more and more migrations means you are doing it correct. (Because most of the time when you need alterations to to an existing table you simple cannot drop the table and re-create it).
But having said that it always a good idea to run rake db:migrate every now and then (for an isolated db) just to make sure your migrations are working as a group.

Entity Framework 4 code-based migrations don´t work after calling CreateDatabaseIfNotExist

I have a MVC 3 project were I use code based migrations together mith automatic migrations(this works).
When I install this project on a new server the database is created by CreateDatabaseIfNotExist initializer, cause I´m using the seed method of this. After executing this I have a __MigrationHistory table with one entry. The model hash of this entry is exactly the same like the last one from my developement server. On my development server I have an entry for each of my code based migration in the __MigrationHistory table.
Now the problem is that when I try to run the migrations on the new server, I expected them to say to me "nothing to do, cause model hash is same", but instead of this the migrations seems to look only for the MigrationId in the database and try to execute every migration whose MigrationId is missing. Of course this leads to Exceptions, cause the migration tries to add database structures already there.
I think this should be a very common scenario, so is there a kind of workaround for this? My workaround for the moment is to copy all contents from the __MigrationHistory of the development system to the new server, but this is very tricky, due to the dealing with the modelhash as varbinary. Is there a better solution or did I understand some logical things wrong?

Consolidating Rails Migrations on a Long Running Project

I'm working on a project that's accumulated hundreds of migrations, and I'm unsure what to do with them long term. I suppose they're no hurting anything, but it seems strange to keep around a bunch of old files for incremental migrations, some of them creating tables that are later removed.
So far, I've seen three possibilities:
Leave them alone. They're not hurting anything.
Just delete them. I don't see much harm in doing this, since a new developer would be probably be starting with schema load anyway, not migrations.
Delete them all, create a new one with a timestamp matching an old merge, and create a new merge from your schema. This seems very clean, but I'm not sure who would actually use it.
I'm inclined to just delete them, but I'm curious if there's a big pitfall I'm missing.
In my opinion, as soon as every database on the project, especially the production, are at least at version '201xxxxxxxx', it should be fine to delete migrations before that version. They are not technically necessary anymore.
After that, if you want to play archaeology with your database history, you can still use your version control system.
With Git for example, you can use the following commands to have a quick look over the past :
git log --name-only db/migrate/ #to list commit involving migrations + migration filename
git show xxxxx db/migrate #to see the code of commit xxxxx's migration(s)
Alternatively, you can browse repository history of schema.rb, identify a commit and see the corresponding migration content with the command above.
If you prefer to have a lighter db/migrate and use Version control, I would go for a little cleanup.
If you find it more convenient to have the whole migrations history directly available because it's easier to browse, I would go for option 1.
Note: it is very likely that old migrations do not make sense with the current application code. For example, some migrations may refer to class or methods that don't exist anymore.
Using version control to checkout the application at the time the migration was written could also avoid some confusion.
Personally, I lean toward option 1: It's generally true that at some point in any project, the schema is what matters, and the migrations are just a curiosity, but you're right when you say they're not hurting anything. Theoretically the old migrations could be useful for someone who wanted to go back and see how the database was organized at some point in the past.
I don't know of any serious pitfalls in deleting them, but I also don't see an advantage to doing so, unless it's the saving of time scrolling past them when you want to edit a new migration.
I don't think the effort of putting together a single migration that duplicates the schema is beneficial - it's extra work, and that's what the schema is for anyway.
If you work on a project large enough for long enough, there will come a time when you look at all of those extra migrations with disdain and wonder how so many can exist.
You think to yourself, "just delete them...they don't do anything." This is a perfectly logical and normal thought process (especially as a Rails developer, we just love to minimize code and make things efficient!), but don't let the dark side tempt you.
By deleting migrations, you are deleting the historical record of your application's data model, and worse, the logical path you took to get to your current model. This history can help you remember why you did what you did, and didn't do what you didn't do.
Yes, we've all been guilty of deleting migrations from time to time. But you must resist the temptation as the net benefit would only be a few kB and a cleaner migration folder.
Remember:
Those who delete migrations are condemned to repeat them!
In one of our former projects we dropped all migrations, created a new one which would truncate schema_migrations table with manual sql and then copied db/schema.rb contents to it.
Surely this migration is irreversible, however it allowed us to get rid of hundreds of old valueless migrations but still be able to re-create db not from db schema only but from migrations as well.

conflict model names in surveyor gem

I'm about installing surveyor gem, i followed the instructions there but when i executed
this line to install the gem components:
script/rails generate surveyor:install
I got these conflicts
conflict db/migrate/20120716110951_create_questions.rb
Overwrite /home/saka/modares/db/migrate/20120716110951_create_questions.rb? (enter "h" for help) [Ynaqdh] h
I know that the problem is these conflict model names in the gem and in the existing application as i already have a model named Question.
How to resolve this conflict?
This behavior is a result of an design decision in surveyor. We would like to allow people to run rails generate surveyor:install every time they upgrade surveyor, and get new migrations and changed files. The generator finds migrations with the same class name, preserves the timestamp, and presents the conflict to the user if it is different. One thing that may affect your decision moving forward is that if you do maintain your existing create_questions migration, you'll have to contend with this conflict every time you upgrade surveyor. There are a few solutions:
Surveyor could be changed to support name-spaced, configurable, or otherwise modifiable model names. This will most certainly take time, and there are currently no issues for this feature (but feel free to add one).
You could rename your migration and the generator will run. Remove the create_questions and add_correct_answer_id_to_questions migrations, and remove questions from the add_api_ids migration. Make sure your question model matches the surveyor question model as documented in the wiki (there's no guarantee we'll keep the diagram in sync). More definitively, you may create a blank rails project, add surveyor, run the generator and migrations, and then look at db/schema.rb. You'll have to keep your question model in sync with surveyor's manually.
You could rename your model. If it has existing functionality besides surveyor's, you'll probably want to go this route anyway.
How about renaming your Question Model? You Basically have to create a migration for renaming (or change the initial migration if you don't need the migration if you don't have production data yet) and find all occurrences of Question/question in your app and rename them accordingly. It's a bit of work but not a real problem.

Undoing a Migration Error

How do you go about changing column names and types in your rails app? Do you create a new migration to make the changes, or do you rollback, edit your migration file, and then migrate again?
What's the "proper" way to do this in Rails?
It sort of depends on when this happened in your development cycle, If you recently made the change and haven't pushed it out into a public repo, then you indeed might want to do the rollback thing and then edit the migration files and migrate again, just to keep things clean. But if it's a change to a migration that's a few migrations back then you should create a new migration that changes the rows and columns to the "new" old values.
Well, to undo a migration you typically want to roll it back:
bundle exec rake db:rollback
Where VERSION= can also be specified. If you wanted to change it to something entirely new, you would make a new migration. Typically you shouldn't be touching old migrations at all.
Rails gives you the choice of creating a migration and changing it a various of ways. So there is no "ruby developers" technique of choice.
However, every time you create a migration, a file is created, and it represents the history of your development. There are a lot of cases that a simpler file should be uselfull, like a code that other ruby beginners would have to look at and modify. On other cases may be necessary to an advanced developer understand changes and improvements made on the code, specially if it is a code running for a long time (some years maybe).

Resources