exactly what does rake db:migrate do? - ruby-on-rails

Does rake db:migrate only add new migrations, or does it drop all migrations/changes and build everything new?
I think rake is throwing an error because it is trying to access a table attribute in migration 040 that was deleted in migration 042. somehow my DB and rake are out of synch and I want to fix them.
for you experts out there - is it common for rake to get out of synch with migrations? how can I avoid this (no, I do not hand-edit my schema or rake files).

When you use rails migrations, a table called schema_migrations is automatically created, which keeps track of what migrations have been applied, by storing the version number of each migration (this is the number that prefaces the migration name in the file name, ie db/migrate/_20090617111204__migration.rb). When you run rake db:migrate to migrate up, only migrations which have not been run previously (ie. their version is not contained in the table) will be run (for this reason, changing a migration that's already been executed will have no effect when running db:migrate). When migrating down, all versions found in schema_migrations that are greater than the version you are rolling back to will be undone.

Everytime you create a migration using scripts (like script/generate model ...) a new migration is added to the correct directory ready to be synched with the real database.
Actually rake db:migrate just checks which missing migrations still need to be applied to the database without caring about the previouse ones.
Of course if you modify the database using other ways is common to obtain out-of-synch things because as you said you can find yourself applying a migration to something that is changed underneath.

A migration means that you move from the current version to a newer version (as is said in the first answer). Using rake db:migrate you can apply any new changes to your schema. But if you want to rollback to a previous migration you can use rake db:rollback to nullify your new changes if they are incorrectly defined. Caution: by doing so your data will be lost.

Related

Run future Rails migrations after db:schema:load

I feel like this must be a question that has been answered in the past but I could not find anything with Google.
According to the Rails guides:
There is no need (and it is error prone) to deploy a new instance of an app by replaying the entire migration history. It is much simpler and faster to just load into the database a description of the current schema.
However, when you load the database via the schema file there would be no data in the schema_migrations table and therefore any migrations that are added to the project in the future cannot be run without first running the entire migration history.
Am I missing something here? If I create a new instance of the Rails DB from a schema file how can I run any future migrations against it?
It is preferred to set up a new database with a schema load rather than running old migrations, and it should be expected that the schema_migrations table is updated correctly when running a rake db:schema:load. When you run rake db:schema:load the schema_migrations table should be populated based on the value of the version key-pair passed to the ::define method in the db/schema.rb file.
For example:
ActiveRecord::Schema.define(version: 20161208214643) do
end
should update the schema_migrations table up to the migration listed in version. The version value should be populated in the db/schema.rb file automatically after running a rake db:schema:dump or rake db:migrate (which invokes db:schema:dump). This allows for any future migrations to be run normally, as should be expected.
The inserts into the schema_migrations table are handled by the assume_migrated_upto_version method, as seen in the following files:
https://github.com/rails/rails/blob/5-0-stable/activerecord/lib/active_record/schema.rb#L52
https://github.com/rails/rails/blob/5-0-stable/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb#L1021

Rails with existing database keeps saying migration pending

I'm trying to make a new rails project with an existing database.
I create the projects, configure the database.yml and can successfully do a db:schema:dump
This is all based on what I read on this site
http://blog.joelberghoff.com/2013/02/06/ruby-on-rails-tutorial-creating-a-rails-instance-from-an-existing-mysql-db/
And a few others.
After I do the dump, I copied the schema.rb into db/migrate and renamed to 001_createdatabase.rb as indicated in his tutorial.
Everything seems fine. However I cannot run the site as it tells me i have migrations pending. and the db:migrate:status indicates its that 001_createdatabase.rb that I created.
So based on that:
Was creating that 001_createdatabase migration from the schema.rb the right thing to do?
If it was how do I get rails to understand that it doesn't need to run that one as its already done?
Where does rails check to see if it has pending migrations. Obviously it must check the db/migrate folder and compare it to what?
Thanks
It would seem that in order to get credit for having run the migration, you need to actually run the migration. The migration, 001_createdatabase.rb, represents the migration that will take you from having an empty database -- no tables, no data -- to having your first version of the database. When you run rake db:migrate, rails checks to see if every file in the db/migrate directory has been run by looking for the numerical part of the migration file name in the schema_migrations table.
In your case, you've not run the migration, there is no entry in the schema_migrations table, so rails thinks, rightly, there is a migration to run.
To fix the issue, you can put the record that the migration has been run into schema_migrations or actually run the migration. You may need to create the schema_migrations table, rails will create it as needed.
If you want to run the migration, either drop your database (or create a new one -- you can drop the old one when this works), and point your rails application to the new database. run rake db:create and rake db:migrate. When it completes, you should have a new copy of your database, but one that has been created by the rails migration process. The schema_migrations table should have a record with 1 in the version column.

How do I update migrations when upgrading from a Rails 1.2.3 app?

I'm updating a Rails 1.2.3 app to 3.2.1.
I'm trying to figure out how I can update the migration structure to be compatible with the latest version of Rails, so that, ideally, you can just run rake db:migrate when setting up the app. Currently, I have solved this by just doing rake db:migrate:up VERSION=[version_number] of whatever migration I need to run. If I just run rake db:migrate, it tries to rerun all of the migrations from the beginning and it stops (since those migrations have already been run in the db dump I have).
Migrations in the app look like this 001_add_some_model.rb, 002_add_some_other_model.rb instead of 20120209182512_add_some_model.rb.
Does anyone have any experience with this? How can I fix this?
I think you should restart your migrations, drop all the migration you have and create a new migration with definitions of your current models. See this migration as a starting example.
It is not recommended to run all migrations to set up a new database even in an up-to-date Rails 3 app. This is explained in db/schema.rb:
Note that this schema.rb definition is the authoritative source for your
database schema. If you need to create the application database on another
system, you should be using db:schema:load, not running all the migrations
from scratch. The latter is a flawed and unsustainable approach (the more migrations
you'll amass, the slower it'll run and the greater likelihood for issues).
Instead of what had been suggested, I would create new migrations from scratch.
Start you all your models at the current state and create new migrations for each of them, this way you could still use the power of the migrations later, like adding a column to a table or change a column type.
If you create a singe migration for all your models, like has been suggested you'll loose the model track in migrations name.
This is just another way to do it and reflects my own vision.

How to rollback to beginning and recreate/rebuild new migrations

So this is my first real Ruby on Rails project. I've learned my lesson -- I didn't make all changes using migrations so things are a bit messed up.
What's the best way to start over with new migration files and rebuild the schema, etc? My project is too far along to rebuild the entire project, but not far enough along to where I care about losing the migrations I have thus far. I also don't mind losing the data in the database. I was trying to rollback to the beginning but some of it is failing.
I know this is a bad state to be in, but lesson learned.
EDIT:
I just deleted all the migrations files and rebuilt the schema file with db:schema:dump.
I assume this puts me in a clean state with my existing database, just lost migrations.
if you want to migrate some steps back you can
rake db:rollback STEP=2
That command will migrate your database 2 migrations back.
If you need more help with rake commands, jus type
rake -T
That command will list all the tasks you have in you application.
If you are not concerned about losing data then do
rake db:purge
It should just drop your database
Your schema.rb file should contain the actual schema from your database. You could use it as a starting point to create you migrations. You could create a new migration for each table with the :force => true parameter to overwrite the old table. Afterwards you could just delete the old migrations (you would probably also need to delete their entries from schema_migrations table).
Another options would be just updating the old migrations to match your current schema.

how to avoid a faulty rollback migration in ruby?

i have a bug in a "self.drop" in a migration such that I cannot roll back past that migration. how can i start from scratch and build up from migration 001? also, is there a way to do this without losing my data (it's just testing, but still...)
You can comment all statements in self.down migration and rollback to previous db version.
Then apply changes by hand using a gui/web db client to match db schema before migration.
After you will be able to run migration again and your data will not be lost.
rake db:drop
rake db:create
rake db:migrate
It will reset your database and run all migrations. If you don't want to lose your data you can save it using plugin yaml_db:
rake db:data:dump # stores all data in db/data.yml
...
rake db:data:load # loads db/data.yml to database
If you have an error in a migration you can edit it and then try to rollback.
I realise this is an old question, but imho still relevant. If you want to recreate your database from scratch, one does not rollback and rerun migration, one just does
rake db:setup
This will drop, create and fill the database with the current combined state of all the migrations. This is because, definitely in a large system, running all the migrations might no longer work. However, running the schema.rb will always work.
My advice would also be to avoid rollback of migrations as much as possible, unless when you just created a migration and want to make some addition/typo/fix, before having pushed the migration to your team or any deployment.

Resources