What if we mistakenly deleted some migration file..? - ruby-on-rails

I have deleted some migration file mistakenly. Those files are already migrated.
If I am creating migration with same name, and fire rake db:migrate command it is showing me message that Table already exist. Is there any way to regain those files?
please help..

You will find information about previous migration in config/schema.rb
There is no need of keeping old migration files if all databases (developers, staging and production) have been migrated. Even if you did not delete the old files, they would not prevent you from getting a error message if you try to create a duplicate table.

I am relatively new to RoR. However, I'm a bit concerned that losing this file will present some problems if you aspire to host your app on a server other than the one it is currently hosted on. For example, if you had a mind to host the app in Heroku, you would need to run your migrations in that environment.
If you are not terribly far along with your application, it would be best to start over, take care not to delete your migrations, and put your app under version control so that you will have a fallback should you run into this problem in the future.

Related

Can I manually create migrations for production in Heroku, Ruby on Rails?

I have created an application with Ruby and Rails. The thing is that when I was develpoing it, I had some problems with the migrations, because I created them but with a wrong syntax. What happened is that I deleted some of the files because sold migrations that didn´t work had the same name than the new ones, but in the middle of that I accidentally deleted some of the migrations (obviously after running rails db:migrate) that the project uses actually. So for instance, i have the Service table, which is related to the Reservation table because Service has reservation_id, but i don´t have the migration file that says AddReservationIdToService.
So now I want to use Heroku for production. the thing is that O have to change to postgresql because Heroku doesn't support sqlite. So i have to run the de:migrate again to create the tables and relationships in the new DB, but I need the files that I explained that I deleted. The question is:
Can I create the migrations manually, so when i run db:migrate for postgres the full structure of the database is created without lacking relations?
You don't really need the migrations to recreate the existing DB -- in fact it's not a good idea to try for a couple of reasons (including the missing migration file problem you encountered). You can simply run:
bin/rails db:schema:load
to populate a new database from the existing schema. If for some reason you haven't got a db/schema.rb checked under version control you can run:
bin/rails db:schema:dump
against the sqlite version to re-create a fresh schema file from the database.
You can also keep your migrations list tidy by occasionally zapping really old migrations, since all the cumulative changes are captured in the schema file.
Yes, you might create another couple of migration files.
Certify you have now the tables you wish locally with your sqlite. Draw these table in a piece of paper (or where it be the best fr you), then check this official API documentation of Rails.
Delete all migrations made before and create another according to the tables you drew.
The workflow is gonna be like:
1) "I need to create a table called Reservation, where is it shown on the documentation?"
2) "I need a table called Service, where is it shown on the documentation?
3) "I need to add a column with a foreign key to service named reservaton_id, how does this documentation says it?
For all this steps above, create the correspondent migration file as you normally have done.
The main difference here is not to run the migration locally. Instead, push your new version app to your heroku remote branch and there you run the migration, like:
heroku run rails db:migrate
Remember to not run this same migration locally because you already have these tables locally.
The last two advise is:
1) If your migration doesn't go as you expect, don't delete the migration file. Instead, run rails db:rollback and try again.
2) Keep tracking your migration files on the same branch of your version control.

Rails Migrations Convention

I've started working with rails recently and I have noticed that during development you can end up with a lot of migration files as your ideas change and your database with it. Is there a convention in rails to avoid accumulating a lot of migrations and deleting redundant ones (such as one migration adding a table and then the next deleting it)? Or, is it preferred to keep all your migrations and never delete them? Thanks.
If you are working on a team it is preferred and you always should keep all the migrations.
Suppose you push a migration to Git and later found out that it needs some change. So you revert and delete the migration and create a new one and push the new changes. It works well in your machine. But if somehow your previous faulty migrations are run by any of your team mate and he pull the new code he will have to run the new migrations which will break the applications in your teammates machine.
But if you are working solo and want to get a bit tidy then you can carefully delete migrations after reverting them (Not preferred).
The primary job of migration files is to alter the database schema. Deleting redundant ones (such as one migration adding a table and then the next deleting it) will not cause any problems and it free up some disk space and slug size.

Can I deploy to Heroku without destroying existing database? Ruby on Rails

I have made quite a large upgrade to my app. I have older version deployed on Heroku at the moment. Problem is that I have added/removed quite few migrations in the process of making my app more modular. I do not want to lose my registered user table that is already up on Heroku while deploying the update. Are there any tips someone can offer on how to preserve my user table while upgrading the app? I do have backup add-on installed but I have no clue what to do with that file.
You should then setup your migrations more carefully since that one, which is last presented on the heroku server. So, when:
you are adding a column, just setup defualt value
you remove the column, you shell export data to (for example) YAML, and store it in the tmp/.
you are reconstructing parts of the colunms by adding and remove some of them, in migration carefully copy required data from older column (prepared to deletion) to newly created ones.
If you're that concerned about deploying I think you might need to declare migration bankruptcy.
Create a new migration that drops the current schema and copy the new database schema into it
Dump out the contents of your database as CSV ( https://coderwall.com/p/jwtxjg/simple-export-to-csv-with-postgres ) or using Rails to dump in some other way (YAML etc.)
Write a Rake task to parse the data dump into your new schema
Set up a new database on Heroku Postgres (this does not delete the old data)
Do a dry run locally to make sure it all works
Promote the new database to DATABASE_URL
Deploy, migrate, run the Rake task
Not very nice and not something you can roll back from easily if it goes wrong.

What's a good way to clean up my migrations in Rails?

So I've been working on this web app for a year now and I would like to compile to schema into ONE migration, that way my text editor loads faster, git working directory isn't so cluttered.
Search find will be faster.
Any my config/db won't be 4000px long.
Remove the migration files once you've migrated your servers. If you ever want to start with a fresh deployment, run rake db:schema:load or rake db:setup. You shouldn't be re-running all your migrations as explained here.
You don't need to keep your migrations around forever, you are free to delete them as soon as you're sure you don't need them anymore. Just go into your db/migrate/ directory and delete the migrations that are older than, say, a couple months.
As long as all the migrations that you want to delete have been applied everywhere (i.e. development and production) then you don't need them anymore (unless you want to go backwards). Really, migrations aren't meant to be permanent files, they're just around to get you from A to B and then they're just baggage.
One way to go is to take a blank database and run all the migrations. Now you've got all the template data which you can save to a yaml. The yaml plus the schema should be enough to bring the DB back without running any of your previously existing migrations.
However, other answers should mention an existing tool or gem for doing this.
Given that none of the answers mention it, this is the gem that does the job: https://github.com/jalkoby/squasher
It basically reruns the migrations from scratch until the date you specify, and then loads the resulting db/schema.rb into an initial migration that replaces the old ones. It can also cleanup the schema_migrations table so you don't get those
up <timestamp> ********** NO FILE **********
entries when running rake db:migrate:status.

Is it a good idea to purge old Rails migration files?

I have been running a big Rails application for over 2 years and, day by day, my ActiveRecord migration folder has been growing up to over 150 files.
There are very old models, no longer available in the application, still referenced in the migrations. I was thinking to remove them.
What do you think? Do you usually purge old migrations from your codebase?
The Rails 4 Way page 177:
Sebastian says...
A little-known fact is that you can remove old migration files (while
still keeping newer ones) to keep the db/migrate folder to a
manageable size. You can move the older migrations to a
db/archived_migrations folder or something like that. Once you do trim
the size of your migrations folder, use the rake db:reset task to
(re-)create your database from db/schema.rb and load the seeds into
your current environment.
Once I hit a major site release, I'll roll the migrations into one and start fresh. I feel dirty once the migration version numbers get up around 75.
I occasionally purge all migrations, which have already been applied in production and I see at least 2 reasons for this:
More manageable folder: it is easier to spot a new migration.
Cleaner text search results: global text search within a project does not lead to tons of useless matches because of some 3-year-old migration when someone added or removed some column which anyway does not exist anymore.
They are relatively small, so I would choose to keep them, just for the record.
You should write your migrations without referencing models, or other parts of application, because they'll come back to you haunting ;)
Check out these guidelines:
http://guides.rubyonrails.org/migrations.html#using-models-in-your-migrations
Personally I like to keep things tidy in the migrations files. I think once you have pushed all your changes into prod you should really look at archiving the migrations. The only difficulty I have faced with this is that when Travis runs it runs a db:migrate, so these are the steps I have used:
Move historic migrations from /db/migrate/ to /db/archive/release-x.y/
Create a new migration file manually using the version number from the last run migration in the /db/archive/release-x.y directory and change the description to something like from_previous_version. Using the old version number means that it won't run on your prod machine and mess up.
Copy the schema.rb contents from inside the ActiveRecord::Schema.define(version: 20141010044951) do section and paste into the change method of your from_previous_version changelog
Check all that in and Robert should be your parent's brother.
The only other consideration would be if your migrations create any data (my test scenarios contain all their own data so I don't have this issue)
Why? Unless there is some kind of problem with disk space, I don't see a good reason for deleting them. I guess if you are absolutely certain that you are never going to roll back anything ever again, than you can. However, it seems like saving a few KB of disk space to do this wouldn't be worth it. Also, if you just want to delete the migrations that refer to old models, you have to look through them all by hand to make sure you don't delete anything that is still used in your app. Lots of effort for little gain, to me.
See http://edgeguides.rubyonrails.org/active_record_migrations.html#schema-dumping-and-you
Migrations are not a representation of the database: either structure.sql or schema.rb is. Migrations are also not a good place for setting/initializing data. db/seeds or a rake task are better for that kind of task.
So what are migrations? In my opinion they are instructions for how to change the database schema - either forwards or backwards (via a rollback). Unless there is a problem, they should be run only in the following cases:
On my local development machine as a way to test the migration itself and write the schema/structure file.
On colleague developer machines as a way to change the schema without dropping the database.
On production machines as a way to change the schema without dropping the database.
Once run they should be irrelevant. Of course mistakes happen, so you definitely want to keep migrations around for a few months in case you need to rollback.
CI environments do not ever need to run migrations. It slows down your CI environment and is error prone (just like the Rails guide says). Since your test environments only have ephemeral data, you should instead be using rake db:setup, which will load from the schema.rb/structure.sql and completely ignore your migration files.
If you're using source control, there is no benefit in keeping old migrations around; they are part of the source history. It might make sense to put them in an archive folder if that's your cup of coffee.
With that all being said, I strongly think it makes sense to purge old migrations, for the following reasons:
They could contain code that is so old it will no longer run (like if you removed a model). This creates a trap for other developers who want to run rake db:migrate.
They will slow down grep-like tasks and are irrelevant past a certain age.
Why are they irrelevant? Once more for two reasons: the history is stored in your source control and the actual database structure is stored in structure.sql/schema.rb. My rule of thumb is that migrations older than about 12 months are completely irrelevant. I delete them. If there were some reason why I wanted to rollback a migration older than that I'm confident that the database has changed enough in that time to warrant writing a new migration to perform that task.
So how do you get rid of the migrations? These are the steps I follow:
Delete the migration files
Write a rake task to delete their corresponding rows in the schema_migrations table of your database.
Run rake db:migrate to regenerate structure.sql/schema.rb.
Validate that the only thing changed in structure.sql/schema.rb is removed lines corresponding to each of the migrations you deleted.
Deploy, then run the rake task from step 2 on production.
Make sure other developers run the rake task from step 2 on their machines.
The second item is necessary to keep schema/structure accurate, which, again, is the only thing that actually matters here.
It's fine to remove old migrations once you're comfortable they won't be needed. The purpose of migrations is to have a tool for making and rolling back database changes. Once the changes have been made and in production for a couple of months, odds are you're unlikely to need them again. I find that after a while they're just cruft that clutters up your repo, searches, and file navigation.
Some people will run the migrations from scratch to reload their dev database, but that's not really what they're intended for. You can use rake db:schema:load to load the latest schema, and rake db:seed to populate it with seed data. rake db:reset does both for you. If you've got database extensions that can't be dumped to schema.rb then you can use the sql schema format for ActiveRecord and run rake db:structure:load instead.
Yes. I guess if you have completely removed any model and related table also from database, then it is worth to put it in migration. If model reference in migration does not depend on any other thing, then you can delete it. Although that migration is never going to run again as it has already run and even if you don't delete it from existing migration, then whenever you will migrate database fresh, it cause a problem.
So better it to remove that reference from migration. And refactore/minimize migrations to one or two file before big release to live database.
I agree, no value in 100+ migrations, the history is a mess, there is no easy way of tracking history on a single table and it adds clutter to your file finding. Simply Muda IMO :)
Here's a 3-step guide to squash all migrations into identical schema as production:
Step1: schema from production
# launch rails console in production
stream = StringIO.new
ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, stream); nil
stream.rewind
puts stream.read
This is copy-pasteable to migrations, minus the obvious header
Step 2: making the migrations without it being run in production
This is important. Use the last migration and change it's name and content. ActiveRecord stors the datetime number in it's schema_migrations table so it knows what it has run and not. Reuse the last and it'll think it has already run.
Example: rename 20161202212203_this_is_the_last_migration -> 20161202212203_schema_of_20161203.rb
And put the schema there.
Step 3: verify and troubleshoot
Locally, rake db:drop, rake db:create, rake db:migrate
Verify that schema is identical. One issue we encountered was datetime "now()" in schema, here's the best solution I could find for that: https://stackoverflow.com/a/40840867/252799

Resources