Rails MYSQL migrations failing only on TEST? - mysql

I can't for the life of me figure out what's going on here, im not SUPER familiar with rails however:
I've modified my database.yml file to point to a new mysql test database instead of sqlite. When doing a RAILS_ENV=test db:drop db:create db:seed on dev it works fine.
HOWEVER it always fails on test, citing a table doesn't exist when being altered by one of the migrations. I tried the exact same .sql file loaded up on the database for dev as on the test db with no errors.
I was able to delete the test db and duplicate the dev database and it would work fine, but for some reason...with migrations it will not work on the test database (which is a freshly created database, but so is the dev technically since I drop and recreate it from scratch with a seed file everytime)
What could cause such a thing? Migrations working fine on a fresh DEV database (Mysql2) and not on a fresh TEST database (Also Mysql2)
for specifics the error is complaining about a table not being able to be altered, because it doesn't exist. (I confirm in SQL Pro that the table doesn't exist as well), but when migrations run on Dev database it works fine (even after being deleted and commands above (but just ran in RAILS_ENV=development) ran.

When you run db:create all it does is create a completely empty database, with no tables... you need to run either db:migrate or db:test:prepare in order for the actual tables (empty of data) to be added to the test database.
So your usual run should be: db:drop db:create db:migrate db:seed
HOWEVER... db:seed isn't going to work the way you want it to... every test completely empties the database of data every time (this is to prevent cross-contamination of test data), and db:seed is to add data to your development environment.
In the test environment you need to duplicate any seed-data into fixtures instead (or use appropriate factories).

Related

Set up some versions on rake db:migrate RAILS_ENV=production

im trying to update my Bitnami Redmine database, by using rake db:migrate RAILS_ENV=production but the problem is that the status says that i have many updates to do, but when i try theses updates i allways receive a message that the column or the table already exists, there is some command to "jump" db to especific version?
You can always "inject" a version into the schema_migrations table to trick the migration system into ignoring them, but TBH I'd be looking into why the migrations are so out of whack.
Worst case, you could always add column_exists? checks to each failing migration, and not add or update a column if it already has been added. But again, you run the risk of your migrations being out of spec with the state of the actual database.

Rails migration appears completed, but rake still shows migration as pending

I ran a simple rails migration on a large MySql2 db to add a column to a table:
class AddMiddleNameToPerson < ActiveRecord::Migration[5.0]
def change
add_column :person, :middle_name, :string
end
end
I was disconnected from the server running the rails app during the migration. I then reconnected and checked the migration status with bundle exec rake db:migrate:status, which showed it as down:
down 20170424182410 Add middle name to person
I assume it was still running in the background. So I left it for some time, and eventually using the rails console I verified that person.middle_name was accessible on objects. However, db:migrate:status still shows the migration as down, and if I try to run db:migrate again I get an error:
Mysql2::Error: Duplicate column name 'middle_name'
So it seems that the new column is in the database, and accessible through ActiveRecord, but rake db:migrate:status finds the migration as down and rake db:migrate attempts to re-run it, unsuccessfully.
If this is a production database (or other database with important data) then do not rake db:reset as that will drop the database and you'll lose everything; also don't db:migrate:down as that will drop the middle_name column and you'll lose whatever middle names you already have.
First get a backup of the database or at least the table you're working with.
Second, connect to the database with the mysql CLI tool and say describe people;. The information in your question suggests that you will see the middle_name column in there but it doesn't hurt to make sure you're connecting to the right database. If middle_name isn't there then you're almost certainly connecting to the wrong database somewhere, if it is there then you just have a migration issue to clean up.
You say that the database connection was dropped before the migration finished. Migrations work in this sequence:
Run the migration to update the database.
Record the migration's version number in the schema_migrations table.
Regenerate db/schema.rb or db/structure.sql.
If 1 completes but the connection is lost then 2 never happens so the migration will have run but Rails won't know it.
If no other environments need the migration then you can simply delete the migration and rake db:schema:dump or rake db:structure:dump to get a fresh schema.rb or structure.sql. Migrations are just temporary bits of code to get you from A to B so deleting them after they've been run everywhere is fine (and even recommended), all that matters long term is your database's structure (which is in db/schema.rb or db/structure.sql).
If other environments need to run the migration then you can manually patch the schema_migrations table; connect to the database with the mysql CLI tool and say insert into schema_migrations (version) values ('20170424182410');. Rails will now know that the migration was run and future rake db:migrate calls will be happy. Then you'd want to refresh your schema.rb (with rake db:schema:dump) or structure.sql (with rake db:structure:dump).
You probably have a db/schema.rb file for tracking your database's structure (including the version numbers of the migrations that have been run). If you do then you'd use rake db:schema:dump to regenerate it. If you have db/structure.sql then you'd use rake db:structure:dump.

After I ran rake db:migrate VERSION=0 and redid the migration, I lost everything in my database

Before I was trying to run rake db:migrate I ran into an error called column duplication so I ran rake db:migrate VERSION=0 instead and ran rake db:migrate again.
Basically I was clearing up my previous migration and by running a new migration from VERSION=0, I was finally able to finish my pending migration and had no issue with column duplication again.
But here's the thing, the command I ran actually cleared up all my previous data. Is there a way to retrieve what I had lost? And what is the safest way to run db:migrate if there's a column duplication error. I really don't want to go back to VERSION=0
Is there a way to retrieve what I had lost?
You deleted your database table and re-created it. All data that was stored in that table was also deleted and is lost. The only way to get your data back is to restore from a backup. Do you have a recent database backup?
And what is the safest way to run db:migrate if there's a column duplication error.
If you migration has an error, fix that migration and re-run it. In you example: If your migration fails with an error telling you that there is a duplicate column, just remove the code that tries to add a duplicate column and re-run the migration.
rails migration has a strict process to be followed. Suppose you have duplicate column. You should write another migration file to remove that duplicate column.
When you have ran
rails db:migrate VERSION=0
It is creating your database all again so obvious that data will be lost.
So make sure any correction in Database used in Rails should follow strict process of creating new migration rather than editing the same.

capistrano 3.1 deploy with new migrations added

Ubuntu, rails 4.1, capistrano 3.1
I deployed my rails app to server with Capistrano, and during this procedure, db:migration was executed and database has been build up.
However, later I created new migrations, and when I use "cap production deploy", it shows my original db misses some table (db:migration not executed on my new migrations); and when I use "cap production deploy:migrate", then capistrano will run all the migrations (including those that have already been executed before), so it report some table already exist (of course they exist before).
My question is, how can I just execute db:migrate on those newly created migrations ?
Thanks
I think I know the answer:
It's nothing wrong with Capistrano!
During the deploy procedure, it will do things by this sequence:
1. udpate code
2. rake assets:precompile
3. rake db:migrate
Step 2 will somehow load the app, which will execute all initializer code. But here I access new db table, which should be created in #3. So this cause table missing error.
Just wonder why loading app during assets:precompile, what's the use of it?
Can we don't do that?

rails: changing database

I have created an app using a badly named database, all alterations to important data in the database have been done in fixtures so that I can just drop the database, recreate it and then rake migrate the database tables and fill them with the initial data from the fixtures.
I would like to change the name of my database now, so I updated the database.yml file to reflect another database name. I created the database in mysql and then tried to run the migration and fixtures.
Running the migration with trace shows that it is running commands to create tables etc. However once I am finished I get errors in my application saying that the tables don't exist in the new database.
I go into mysql and check the database and it is completely empty. I have tried wiping everything and running the migrations a few times but nothing changes. Is there something I am missing?
I don't know what commands you used to do the migration, but to migrate a production database (which I infer from the tag, "production-environment"), you have to do:
RAILS_ENV=production rake db:migrate
If that's not the answer, then please provide the command you used to perform the migration, which database you expected to be affected, and the relevant bits of database.yml.