capistrano 3.1 deploy with new migrations added - mysql

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?

Related

Heroku Rails mySql (mysql2 gem) migrations

Been able to make migrations (add columns etc) on my local machine with mysql.
But when trying to push these migrations to Heroku, they continue to fail.
The first table in my migration file gets tagged with:
Mysql2::Error: Table 'xxxxx' already exists
locally all my migrations showing as:
up 20171127214206 Add tags to business
but when running heroku run rake db:migrate:status
down 20171127214206 Add tags to business
i don't mind losing all the data at this point as i'm working in a development version on Heroku and will merge later with production
been working on this issue for over a day, so any and all advice appreciated.
according to this and many other sources, it appears you're better to use postgresql adapter with heroku. If you want to do that, you need to edit your database.yml similar to this

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.

Rails MYSQL migrations failing only on TEST?

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).

rails db:migrate doesn't work after altering the database manually

I am still new to rails and I have some questions regarding rails migration.
I am using rails 5, windows 8. I generated a model and wrote some code which creates a table with columns. Then I deleted that table from my development db (MySQL) and tried to execute db:migrate again to see if it would create the table and columns written in the migration file. After executing db:migrate, it didn't show any messages in the terminal and it did not create the table and the columns.
Based from my observation, deleting the version of my migration file from schema_migrations and running db:migrate once again, it worked and created the table and columns.
I would like to ask the pros of rails development on why is this happening and what should I do when I start to develop a large database model.
I would also like some suggestions about great resource materials for learning ruby on rails.
Thanks!
Its because rake db:migrate is running only migrations for the current env that have not run yet. So if you run db:migrate and then manually delete table form DB, your app does not know that.
MIgration Guides

How can you get a sql script of changes from Rails migrations (for MySQL)?

I've seen http://github.com/muness/migration_sql_generator, but it doesn't work properly with MySQL for certain important operations. Is there any other way we can capture the sql generated during a rails migration?
The reason I'm asking is that I cannot run the migrations on the production server since it is maintained by technical support (and never touched by developers) at my company. Developers provide a JRuby on Rails war file to tech support and they deploy it via Tomcat. But convincing tech support to install JRuby and Rails just to run the migrations on production is definitely not going to be easy. We want to keep the deployment really simple and with as few dependencies as possible.
We want to simply provide them with a war file and a sql script with db changes.
You may be able to use some kind of tool to generate a diff of two databases. There's a question on that here.
If you diff your test database with your development database just after running the migration that would probably be the easiest way. It might even be worth adding a rake task to do it; get that rake task to depend on the migration and then you could use the new task instead of rake db:migrate to generate a diff each time you migrate.
I actually ended up creating a rake task which monkey-patched Activerecord's sql execution method to also output all sql to a log file (log/database.log). So, the task could be run right before db:migrate like so: rake db:log db:migrate. After that, you can extract the statements which are relevant and put them into a db/sql_migrations/<migration name>.sql file and have your database admins run that when they're ready.
Thankfully I've changed jobs and don't have to deal with that mess of a process anymore though. :)