660

The difference between rake db:migrate and rake db:reset is pretty clear in my head. The thing which I don't understand is how rake db:schema:load different from the former two.

Just to be sure that I am on the same page:

  • rake db:migrate - Runs the migrations which haven't been run yet.
  • rake db:reset - Clears the database (presumably does a rake db:drop + rake db:create + rake db:migrate) and runs migration on a fresh database.

Please help to clarify, if my understanding has gone wrong.

ekremkaraca
  • 1,429
  • 2
  • 17
  • 36
Gaurav Agarwal
  • 13,952
  • 4
  • 27
  • 39
  • 10
    Does `rake --tasks` help ? – zx1986 Nov 28 '14 at 02:42
  • You should check this blog. http://jacopretorius.net/2014/02/all-rails-db-rake-tasks-and-what-they-do.html – Bishisht Bhatta May 03 '16 at 14:16
  • Your understanding of `rake db:migrate` is correct, but your understanding of `rake db:reset` is wrong. See the topmost answer, from moritz. – Magne Jun 08 '17 at 13:54
  • 1
    BTW, as of Rails 5, these commands can be invoked as `rails db:migrate`, `rails db:reset`, `rails db:schema:load`. See https://stackoverflow.com/questions/38403533/rails-dbmigrate-vs-rake-dbmigrate – Purplejacket Sep 10 '19 at 18:01

5 Answers5

1384
  • 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.

I hope that helps.


UPDATE 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: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)

jshah
  • 1,327
  • 2
  • 14
  • 33
moritz
  • 23,869
  • 3
  • 39
  • 36
  • 17
    Here is the file with answers :) - https://github.com/rails/rails/blob/master/activerecord/lib/active_record/railties/databases.rake – cutalion Apr 24 '12 at 16:54
  • 3
    @cutation: db:setup does surely not run db:migrate, because it would be much too brittle to run all migrations just for a db setup (this is what schema.rb is for). – moritz Apr 25 '12 at 09:10
  • 2
    I'm executing db:reset and it's seeding my db. Why could it be? – Alejandro Riedel Feb 11 '13 at 00:17
  • 1
    **db:setup** also runs `db:create` if necessary. At least as of rails 4.0.2. – Dan Feb 13 '14 at 16:40
  • Rails 4 will perform `rake db:migrate` when calling `rake db:setup` if there are pending migrations but won't execute pending migrations. – Pooyan Khosravi Oct 31 '14 at 12:47
  • As of Rails 5, you can run rake tasks with the `rails` keyword - eg `rails db:migrate` – Fred Willmore Jun 15 '16 at 19:24
  • I just ran `rake db:setup` for a new Rails v6.0.0 project and got the message "db/schema.rb doesn't exist yet. Run `rails db:migrate` to create it, then try again", so it seems it doesn't run `db:migrate` for this version. – iain Aug 30 '19 at 06:54
  • Was not aware of `db:migrate:reset`, and it ended up being exactly what I needed. Thanks! – Chris Scott Mar 18 '20 at 00:45
  • does `db:setup` also create the users/roles? – Ridhwaan Shakeel Nov 03 '20 at 14:54
  • just fyi: `db:setup` will drop your local development database. `db:setup` ends up running `db:schema:load_if_ruby` which runs `db:schema:load`. This reloads the current schema that purges all your current data in the database. – jshah Jan 28 '21 at 23:46
  • Please consider adding the newer answer to the top, and older answer to the bottom, as rails 3.x is quite old now – stevec Mar 01 '21 at 13:43
  • Seems that `db:setup` also do a `db:drop` ?? My db got "reset" every time I do a `db:setup` :/ ... – Hellfar Mar 09 '21 at 21:03
25

TLDR

Use

  • rake db:migrate If you wanna make changes to the schema
  • rake db:reset If you wanna drop the database, reload the schema from schema.rb, and reseed the database
  • rake db:schema:load If you wanna reset database to schema as provided in schema.rb (This will delete all data)

Explanations

rake db:schema:load will set up the schema as provided in schema.rb file. This is useful for a fresh install of app as it doesn't take as much time as db:migrate

Important note, db:schema:load will delete data on server.

rake db:migrate makes changes to the existing schema. Its like creating versions of schema. db:migrate will look in db/migrate/ for any ruby files and execute the migrations that aren't run yet starting with the oldest. Rails knows which file is the oldest by looking at the timestamp at the beginning of the migration filename. db:migrate comes with a benefit that data can also be put in the database. This is actually not a good practice. Its better to use rake db:seed to add data.

rake db:migrate provides tasks up, down etc which enables commands like rake db:rollback and makes it the most useful command.

rake db:reset does a db:drop and db:setup
It drops the database, create it again, loads the schema, and initializes with the seed data

Relevant part of the commands from databases.rake


namespace :schema do
  desc 'Creates a db/schema.rb file that is portable against any DB supported by Active Record'
  task :dump => [:environment, :load_config] do
    require 'active_record/schema_dumper'
    filename = ENV['SCHEMA'] || File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, 'schema.rb')
    File.open(filename, "w:utf-8") do |file|
      ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, file)
    end
    db_namespace['schema:dump'].reenable
  end

  desc 'Loads a schema.rb file into the database'
  task :load => [:environment, :load_config, :check_protected_environments] do
    ActiveRecord::Tasks::DatabaseTasks.load_schema_current(:ruby, ENV['SCHEMA'])
  end

  # desc 'Drops and recreates the database from db/schema.rb for the current environment and loads the seeds.'
  task :reset => [ 'db:drop', 'db:setup' ]

namespace :migrate do
  # desc  'Rollbacks the database one migration and re migrate up (options: STEP=x, VERSION=x).'
  task :redo => [:environment, :load_config] do
    if ENV['VERSION']
      db_namespace['migrate:down'].invoke
      db_namespace['migrate:up'].invoke
    else
      db_namespace['rollback'].invoke
      db_namespace['migrate'].invoke
    end
  end
Community
  • 1
  • 1
sudo bangbang
  • 19,198
  • 7
  • 64
  • 71
  • So if you create your production schema using db:schema:load(created from a series of previous migrations), will rake know which migrations(the ones which took part in creating the initial schema.rb) do not need to be run on future invocations of db:migrate? –  Feb 15 '17 at 17:59
2

As far as I understand, it is going to drop your database and re-create it based on your db/schema.rb file. That is why you need to make sure that your schema.rb file is always up to date and under version control.

Simon Bagreev
  • 2,830
  • 1
  • 21
  • 23
2

Rails 5

db:create - Creates the database for the current RAILS_ENV environment. If RAILS_ENV is not specified it defaults to the development and test databases.

db:create:all - Creates the database for all environments.

db:drop - Drops the database for the current RAILS_ENV environment. If RAILS_ENV is not specified it defaults to the development and test databases.

db:drop:all - Drops the database for all environments.

db:migrate - Runs migrations for the current environment that have not run yet. By default it will run migrations only in the development environment.

db:migrate:redo - Runs db:migrate:down and db:migrate:up or db:migrate:rollback and db:migrate:up depending on the specified migration.

db:migrate:up - Runs the up for the given migration VERSION.

db:migrate:down - Runs the down for the given migration VERSION.

db:migrate:status - Displays the current migration status.

db:migrate:rollback - Rolls back the last migration.

db:version - Prints the current schema version.

db:forward - Pushes the schema to the next version.

db:seed - Runs the db/seeds.rb file.

db:schema:load Recreates the database from the schema.rb file. Deletes existing data.

db:schema:dump Dumps the current environment’s schema to db/schema.rb.

db:structure:load - Recreates the database from the structure.sql file.

db:structure:dump - Dumps the current environment’s schema to db/structure.sql. (You can specify another file with SCHEMA=db/my_structure.sql)

db:setup Runs db:create, db:schema:load and db:seed.

db:reset Runs db:drop and db:setup. db:migrate:reset - Runs db:drop, db:create and db:migrate.

db:test:prepare - Check for pending migrations and load the test schema. (If you run rake without any arguments it will do this by default.)

db:test:clone - Recreate the test database from the current environment’s database schema.

db:test:clone_structure - Similar to db:test:clone, but it will ensure that your test database has the same structure, including charsets and collations, as your current environment’s database.

db:environment:set - Set the current RAILS_ENV environment in the ar_internal_metadata table. (Used as part of the protected environment check.)

db:check_protected_environments - Checks if a destructive action can be performed in the current RAILS_ENV environment. Used internally when running a destructive action such as db:drop or db:schema:load.

Joshua Pinter
  • 37,288
  • 19
  • 208
  • 218
0

You could simply look in the Active Record Rake tasks as that is where I believe they live as in this file. https://github.com/rails/rails/blob/fe1f4b2ad56f010a4e9b93d547d63a15953d9dc2/activerecord/lib/active_record/tasks/database_tasks.rb

What they do is your question right?

That depends on where they come from and this is just and example to show that they vary depending upon the task. Here we have a different file full of tasks.

https://github.com/rails/rails/blob/fe1f4b2ad56f010a4e9b93d547d63a15953d9dc2/activerecord/Rakefile

which has these tasks.

namespace :db do
  task create: ["db:mysql:build", "db:postgresql:build"]
  task drop: ["db:mysql:drop", "db:postgresql:drop"]
end

This may not answer your question but could give you some insight into go ahead and look the source over especially the rake files and tasks. As they do a pretty good job of helping you use rails they don't always document the code that well. We could all help there if we know what it is supposed to do.

Douglas G. Allen
  • 1,989
  • 18
  • 18
  • Please quote relevant parts of the article in case it is removed. Don't suggest doing something without explaining why. – PhilT Dec 02 '16 at 09:21