How Does Rake Db::Migrate Actually Work

How does rake db::migrate actually work

Note: This is true so far as Rails 2.x. It may not hold true for rails 3, as I haven't spent as much time with Rails 3 as I would have liked.

Rails creates a special hidden table named schema_migrations. This table has a single column named version. And there is a row in this column for every migration you have. The value being the timestamp that matches the migrations filename timestamp.

When you migrate, it looks through all your migrations in chronological order (also happens to be alphabetical order due to the timstamp based naming convention). For every migration it looks for a matching row in the schema_migrations table. If it fails to find one, then it runs that migration, and adds the timestamp the table. If it does find one, it assumes it already ran and simply skips it.

The result is that 2 developers can both commit migrations in any order, and it's fine. This is because Rails knows exactly what migrations have been run and which haven't, regardless of when your database first saw them.

So to do something yourself like this, you simply need a way to permanently store this state about which steps been taken and which have not.

exactly what does rake db:migrate do?

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.

Difference between rake db:migrate db:reset and db:schema:load

  • db:migrate runs (single) migrations that have not run yet.

  • db:create creates the database

  • db:drop deletes the database

  • db:schema:load creates tables and columns within the existing database following schema.rb. This will delete existing data.

  • db:setup does db:create, db:schema:load, db:seed

  • db:reset does db:drop, db:setup

  • db:migrate:reset does db:drop, db:create, db:migrate

Typically, you would use db:migrate after having made changes to the schema via new migration files (this makes sense only if there is already data in the database). db:schema:load is used when you setup a new instance of your app.



For rails 3.2.12:

I just checked the source and the dependencies are like this now:

  • db:create creates the database for the current env

  • db:create:all creates the databases for all envs

  • db:drop drops the database for the current env

  • db:drop:all drops the databases for all envs

  • db:migrate runs migrations for the current env that have not run yet

  • db:migrate:up runs one specific migration

  • db:migrate:down rolls back one specific migration

  • db:migrate:status shows current migration status

  • db:rollback rolls back the last migration

  • db:forward advances the current schema version to the next one

  • db:seed (only) runs the db/seed.rb file

  • db:schema:load loads the schema into the current env's database

  • db:schema:dump dumps the current env's schema (and seems to create the db as well)

  • db:setup runs db:create db:schema:load db:seed

  • db:reset runs db:drop db:setup

  • db:migrate:redo runs (db:migrate:down db:migrate:up) or (db:rollback db:migrate) depending on the specified migration

  • db:migrate:reset runs db:drop db:create db:migrate

For further information please have a look at https://github.com/rails/rails/blob/v3.2.12/activerecord/lib/active_record/railties/databases.rake (for Rails 3.2.x) and https://github.com/rails/rails/blob/v4.0.5/activerecord/lib/active_record/railties/databases.rake (for Rails 4.0.x)

Rails -- understanding db:migrate

As convention, the file name for these migration classes will be prefixed by a timestamp representation of when these were created (ex. 20110611000000). When you run db:migrate, rails will check a special table in the database which contains the timestamp of the last migration applied to the database. It will then apply all of the migrations with timestamps after that date and update the database table with the timestamp of the last migration. As a result, each migration class is applied exactly once to the database.

Michael Hart was illustrating that if you put all of the migrations into a single file, rails would have a hard / impossible time telling which migrations had been applied and which ones hadn't. The only option at that point would be to drop all the tables in the database and run through all the migrations from the beginning. Functionally that works, but you would lost all your data. Better to move only in the 'forward' direction than back to the beginning and then forward again.

What does rake db:test:prepare actually do?

The rake db:migrate above runs any pending migrations on the
development environment and updates db/schema.rb. The rake
db:test:load recreates the test database from the current
db/schema.rb. On subsequent attempts, it is a good idea to first run
db:test:prepare, as it first checks for pending migrations and warns
you appropriately.

-- http://guides.rubyonrails.org/testing.html

Basically it handles cloning the database so you don't have to run the migrations against test to update the test database.

How does rake db:migrate VERSION=0 work?

It basically runs the very first migration. You can specify any version number you want to migrate your database to.

You probably did "rails generate model ...." twice on the same model, but didn't destroy one of those migrations, it still exists in the "db/migrate/" folder.

I suggest you read a bit about migrations here.

what does rake db:migrate will actually do?

3 )It is not mandatory to run db:migrate. With just the table name in your DB mapped to the Model Name in the application we can access all the attributes of the table in the applicaiton. Migrations are used so that we could manage our tables and databases within our application (without ever going to the mysql terminal to create a table and its attributes). Generally when a application is being developed its database structure changes over time that is when we use our migrations to alter the structure of the table with out going to mysql terminal and more over when we move from development to production. We need not sit and create the whole DB structure again . its already in our migration we just run db:migrate in production mode

2 ) I am not sure (too my knowledge old data will be preserved as far as possible )

1 ) Suppose that at first my migration and the corresponding model says that I have only 5 attributes and I run a db:migrate and get that table in MY Database and after a few days of development I figure out that I need 8 attributes. Then, I change the structure in my migration file and model and then run db:migrate again then my database table structure will be updated with three new attributes.

Why am I asked to run 'rake db:migrate RAILS_ENV=test'?

As of Rails 4.1, the rake db:test:* tasks are deprecated. Instead, your (test|spec)_helper.rb should include:

ActiveRecord::Migration.maintain_test_schema!

This means that your test database will get the correct schema every time your tests run, whether you run them from a Rake task or not.

what is version in rake db migrate

The 20098252345 in rake db:migrate VERSION=20098252345 is just a prefixed number given to the migration file which is located in db/migrate directory.It is just a UTC timestamp(YYYYMMDDHHMMSS) to differ one file from another.The migration file which is generated will look like this 20098252345_create_user_model.rb

From the Guides

Internally Rails only uses the migration’s number (the timestamp) to identify them. Prior to Rails 2.1 the migration number started at 1 and was incremented each time a migration was generated. With multiple developers it was easy for these to clash requiring you to rollback migrations and renumber them. With Rails 2.1+ this is largely avoided by using the creation time of the migration to identify them. You can revert to the old numbering scheme by adding the following line to config/application.rb.

config.active_record.timestamped_migrations = false

Hope it helps!



Related Topics



Leave a reply



Submit