As someone who as ditched old, embarrassing migrations for a flat, updated schema part way through an app development process, I only ever regretted it.
Migrations only run on deployment, so there's no real speed reason to squash them, combine them, rename them, or remove them (unless you are totally ditching whatever is in that migration).
AND, ALL your migrations only run once on your first deploy. From then on, only future migrations will be run. So the overhead is a one-time thing.
Having a few (hundred) migration files is really no big deal.
"But what about the fact that migration #3 adds a column which is later removed by migration #45?" That's how we write software: over time, with changes. It's fine.
If you need to redo indexes and rename fields, write another migration. Call it "CleanupBeforeProductionDeploy" if it'll give you that wonderful sense of cleaned up code.
Reordering columns is useless. This isn't Excel. Don't bother.
If you need to display fields in a certain order, use SQL or .map
or .pluck
or I'm sure a dozen other Ruby or RoR solutions, that's what they are for.
You've done good work, it sounds like your app is nearly ready to deploy. Congratulations, that's a serious milestone. So many of us start scratching something out and never push it across the finish line. Seriously, you should feel good.
Don't procrastinate with meaningless fussing that will just lead to errors.
Go push the code and be happy.
Rant over. If I haven't convinced you, here are some tips to at least keep you safe / sane.
The purpose of the schema is a shortcut for creating a new dB from scratch and just jumping to the end without running every migration.
The schema dump is used, for example, by Heroku when you are creating a backup of your production database.
(Just an aside, I use parity
to get production data from my apps into my development environments so I can work with "real" data).
You could also use a schema dump from the actual database to create a new schema file if something happened to your schema file.
So, you can do this, even though you shouldn't waste your time.
Here would be my order of operations:
Keep writing migrations for all these changes you want to make. Yes, write one or more migrations to make all your changes. Seriously. Let Rails handle versioning and timestamping your schema file as you go. And, this way you can do this in stages and test things out.
For changing your table column orders I'd do the following, it's messy, but it would work:
rename_table :users, :users_disorganized
create_table :users do |t|
...
end
# write some complicated SQL to copy 'users_disorganized' data into 'users'
# safety catch in case copying things over didn't work
drop_table :users_disorganized unless User.all.size.zero?
Use SQL to map and copy the contents of users_disorganized into users.
Here's a good SO post on the topic of SQL inside migrations
SQL is really your only choice here since you don't have an ApplicationRecord Model for UserDisorganized.
Could you make a UserDisorganized model just to make copying the files over easier? Yes, then you'd have to remember delete that file after your production deploy.
Starting to see how time-intensive this is going to be?
Now repeat this process for every table where you want to reorder columns.
- Once you are all done writing migrations, your pristine schema now has the latest timestamp and version and everything so don't mess with these values.
(you can change them, it'll probably be fine, but if you decide to set them too far in the future... then forget about doing that... then write a small migration just to patch a bug or add a feature... then try to run that migration... then spend 4 hours trying to figure out why nothing happens when you run rake db:migrate
... all just to realize the schema timestamp is later than your migration timestamp... and so on)
Now you can gulp delete all your migrations. Yeah. You don't want them? Here's your chance to prove it. You still serious about this?
How do you then initialize your production database? Tell Heroku to run rake db:schema:load
instead of rake db:migrate
.
Good luck.
(and don't bother)