Rails/Heroku - Dropped table and can't get it back - ruby-on-rails

I have screwed up my migrations/schema/db to the point that I can't seem to figure this out.
Locally, I had a comments table. I needed to restructure this table completely, so I opened up my initial "create comments table" migration and altered it manually. I then altered my schema.rb file to match the migration. I then ran rake db:reset and rebuilt my database, and rake db:migrate to finish it off.
This worked seemingly well on my local dev environment. When I pushed to heroku, however, I ran heroku pg:psql and dropped my comments table. I then ran heroku run rake db:migrate thinking it would rebuild the comments table - It did not. The comments table no longer exists, and I can't figure out how to recreate it. I don't have anything important in my heroku database EXCEPT for the users table, so I can't reset the entire thing.
How can I recreate that table, and make sure it matches the migration file I pushed to heroku?

First off, you shouldn't go back into old migrations and manually change them. Just do a new migration with the changes defined there. Read up on migrations here: http://guides.rubyonrails.org/migrations.html
This is done so you don't run into the problem you are currently having. It's also bad practice and if you were working in a group there would be complete mayhem. It's hard to tell exactly what the differences are between your local machine and heroku and what you've changed. My suggestion would be to roll back both your local machine and heroku and do a new migration with your changes.
I'm assuming you are using git so you can go back to a previous version before the change to the create_comments_table on your local machine. You can do the same in Heroku at
https://dashboard.heroku.com/apps/nameofyourapp/activity
In your dashboard you can click on your app and go to the activity tab. There heroku maintains a record of the changes you've pushed. You can rollback to another previous change by hovering over the version.
Now that you have basically restart your app locally and on heroku, you can define a migration with what you want to change in the comments table.
You also might be interested in the PG Backup add-on. Then you won't be as worried about losing data. https://devcenter.heroku.com/articles/pgbackups

Related

After rails migration, resulting schema does not match migrations. Lingering database state?

Rails 6.1.4
Ruby 2.7
Postgresql 14
A dozen or so migrations, one schema.rb file.
I edited a migration, but did not change the migration id. The result is super weird behavior and I wanted to get input on the best approach.
After I incorrectly edited my migrations, I commited and pushed my feature. A team member pulled the feature and ran the migration on their machine. After they did, no matter the branch, the schema would include the changes I added when I originally modified it. But if they were on a different branch than mine, the actual migration files did not have those changes!!
I tried reverting my commit history to pre-migration editing with no luck. This is how I know it's a db issue, albeit caused from git.
So basically, after every migration, a specific model in the schema gets 4 added columns. No matter what, and it's not in a migration file on rails.
And thats the issue.
My question:
How would you go about solving this without resetting the db?
My current approach/best guess:
Lingering state in the db gets generated in the schema.rb file.
If its not in a migration, the only place schema.rb can get the info is from db.
How do I reset the state on stuff in general?
Either rebuild from scratch, or 'install a copy'. From scratch is not an option :)
If I wanted to install a copy, would it be a wise path to:
Revert changes from any migrations after pulling, delete branch.
Pull down fresh copy of branch
DO NOT MIGRATE - Instead, rails db:schema:load
This should copy over the db structure and effectively overwrite any lingering ghost state.
Rails db:migrate -> this will update migrations,
if you did everything right only the schema version number should change
Now things are synced, continue to db:migrate as normal moving forward.
I did this on my local machine and was successful, but I am curious..
Am I understanding this process correctly? Is there an easier way?

What if we mistakenly deleted some migration file..?

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.

Why does schema.rb change (in the eyes of Git) when just running rake db:migrate?

This is a little general I know, but it's been bugging the hell out of me. I've been working on lots of rails projects remotely with Git and every time I do a git pull and see that there is some sort of data change (migration, or schema.rb change) I do a rake db:migrate.
These generally run fine and I can continue working. But if you do a git pull and then git status, your working directory is clean (obviously) then do a rake db:migrate (obviously when there are changes) and another git status and all the sudden your db/schema.rb has changed. I have been just doing a git checkout immediately to reset back to the latest committed version of the schema.rb file, but why should this be necessary?! What is rails doing? Updating a timestamp? I can't seem to figure out what the diff is but maybe I'm just missing something?
The schema enables machines to run rake db:schema:load when being setup for the first time instead of having to run the migrations, which can go out of date if models are renamed or removed, etc. It's supposed to update after a migration, and you always want to latest version checked into source control.
The order of attributes in the dump reflects the order of the attributes in the database, and that can get out of sync if one person has been playing around locally with migrations, running them forwards and backwards manually, and editing things to get them just so. It's possible to create a state where the attribute order in the pusher's schema.rb is different from what everyone else will see when they run the migrations.
If it's easy to recreate your development data, just rebuild the database from schema.rb - then everyone is back in sync (but remember you can't reload the data from a SQL dump that also creates the table - that will recreate the problem. it has to be a data-only dump/load). In the worst case, you can create a migration to delete the column and another to re-add it.
schema.rb reflects your database schema so when you migrate(with changes) it follow that your schema also changes to reflect your db change. I usually add schema.rb to our gitignore, along with database.yml (probably because instead of using schema:load like the one below, i usually do a sql dump when cloning an existing app - but that's just me)

Why is Rails is trying to rerun migrations on production?

On my server when deploying the app for the first time, I ran rake db:setup which loads my entire migration history from schema.rb. Now I have more stuff I want to add, but when I run rake db:migrate on my server I realize it's trying to run my very first migration, which is failing since the table obviously exists.
Examining the schema_migrations table on my production server, I realize it only has one entry in it, which is the migration that was the most current at the time of the initial deployment. Isn't it supposed to have the entire migration history in it? If so, what caused this? If not, why is it doing this?
Did you remember to migrate within the production environment?
rake db:migrate RAILS_ENV=production
I don't know how this happened, but the problem was indeed the fact that the schema_migrations table only contained the timestamp of the most recent migration as opposed to the full history. I manually inserted all of them and it worked fine.
What scares me is that this somehow happened and I don't know how. Oh well.

Why is rake throwing this Rails migration error?

I have two machines... a development machine and a production machine. When I first brought my rails app onto the production server, I had no problem. I simply imported schema.rb by running rake db:schema:load RAILS_ENV=production. All was well.
So, then on my development machine, I made some more changes and another migration, and then copy the new application over to the production machine. I then tried to update the database by running rake db:migrate RAILS_ENV=production. I get the following error:
"There is already an object named 'schema_migrations' in the database."
I'm thinking to myself, ya no kidding Rake... you created it! I ran trace on rake and it seems as if rake thinks it's the first time it's ever ran. However, by analyzing my 'schema_migrations' table on my development machine and my production machine you can see that there is a difference of one migration, namely the one that I want to migrate.
I have also tried to explicitly define the version number, but that doesn't work either.
Any ideas on how I can bring my production server up to date?
Update:
Let me start off by saying that I can't just 'drop' the database. It's a production server with a little over 100k records already in it. What happens if a similar problem occurs in the future? Am, I to just drop the table every time a database problem occurs? It might work this time, but it doesn't seem like a practical long term solution to every database problem. I doubt the problem I'm having now is unique to me.
It sounds like the 'schema_info' table and the 'schema_migrations' table are the same. In my setup, I only have 'schema_migrations'. As stated previously, the difference between the 'schema_migrations' table on the production server and the development machine is just one record. That is, the record containing the version number of the change I want to migrate.
From the book I read, 'Simply Rails 2', it states that when first moving to a production server, instead of running rake db:migrate, one should just run rake:db:schema:load.
If it matters, I'm using Rails version 2.1.
This is a guess, I admit: I think that because you first ran db:schema:load instead of db:migrate in your production environment, you got the structure of your db, but not the data that migrate populates into your schema_info table. So now, when you run migrate in the production environment, there is no data in schema_info which is why migrate believes that it hasn't run yet (because it hasn't).
That said... you say that you have looked in the "schema_migrations" table, and that there is a difference of one version from dev to production... I haven't heard of that table, although I'm a few months behind on my rails version. Maybe you could try creating a "schema_info" table in the production environment, with a single "version" column, and add a row with the version that you believe your production environment to be on.
If you get "There is already an object named 'schema_migrations' in the database." error message then I suspect that you are using MS SQLServer as your database? (As this seems like MS SQL Server error message)
If yes then which ActiveRecord database adapter you are using? (What is your database.yml file, what gems have you installed to access MS SQL Server database?)
Currently it seems that Rails does not find schema_migrations table in production schema and therefore tries to create it and this creation fails with database error message. Probably the reason is upper/lower case characters in schema_migrations table name - as far as I understand MS SQL Server identifiers are case sensitive.
Depending on the system used in production, I have seen instances where the below does not work:
rake db:migrate RAILS_ENV=production
But where this one does work:
RAILS_ENV=production rake db:migrate
Quirky, I know, but it's worth trying it to see if it makes a difference.
Regarding your update:
I don't understand what the difference is between your production schema_migrations and the dev version. Is there a record in both tables (there should be just 1 column, "version", right) or is there a single record in the dev DB and zero records in production? If there are zero records in the production table, then do this:
ActiveRecord::Base.connection.execute("INSERT schema_migrations (version) VALUES(#{my version number that production is supposedly on})")
Alternatively, you could try dropping the schema_migrations table totally on production:
ActiveRecord::Base.connection.execute("DROP TABLE schema_migrations")
Then, re-running rake db:migrate RAILS_ENV=production. That will run migrations from starting from version 1 though, which is probably not what you're after.
Alternatively alternatively, you could start an IRB session in your production environment, do either a "require" or "load" (I can never remember which, or if it matters) of the migration file that you want to load, and then call MyMigrationClass.up. You would need to manually set the version number in the schema_migrations table after that, as you would still have the problem going forward, but as a quick-fix type of hack, that would work.
I would just drop the DB, add it again and run rake rb:migrate. Brad is correct that when you ran the schema load, it didn't put any records in the schema_migrations table.
This is more complicated of course if there is data you can't lose on the production server. You could get the rake backup tasks (not sure if that is part of core or not) and then run rake db:backup:write on your production database, and then after you get the migrations up to date on production, run rake db:backup:read.
schema_info is from an old version of Rails. schema_migrations is the new kid on the block. You should be able to remove the schema_info table as it'll no longer be used. You'll probably want to search for any issues associated with this name change.
rake db:schema:load will load the database structure from schema.rb. This file is the current representation of the database structure. It's used when you have an empty schema (database) that needs all the tables and indexes creating. It saves you having to run all the migrations. If you have an existing production database with data in, you don't want to run it. As others have said that would be bad!
I know this post was some time ago, but I stumbled across it and it hasn't really been answered. As it comes up on google, here goes.
When you did a rake db:schema:dump (or when this was done for you by the build scripts) it will have put the definition of the migrations table into the schema.rb. At the end of the script, the process will try to create the table again, however it obviously exists already. Just remove the migrations table from the schema.rb before running rake:schema:load and there will be no error message.
You will need to set the version number in the migrations table to subsequently run migrations. So it is important to know what version your schema.rb relates too, or delete all the old migrations (they're safely in your SCM right?)
rake db:migrate RAILS_ENV=production
Use the db:schema:load task just for the first creation, incremental changes should be migrated.

Resources