532

I added a table that I thought I was going to need, but now no longer plan on using it. How should I remove that table?

I've already run migrations, so the table is in my database. I figure rails generate migration should be able to handle this, but I haven't figured out how yet.

I've tried:

rails generate migration drop_tablename

but that just generated an empty migration.

What is the "official" way to drop a table in Rails?

Soviut
  • 79,529
  • 41
  • 166
  • 227
Jason Whitehorn
  • 12,933
  • 9
  • 51
  • 68
  • 1
    Since `rails generate migration` has command-line options for generating migration code for creating tables, adding or changing columns, etc., it would be nice if it also had an option for dropping a table -- but it doesn't. Sure, writing the `up` part is simple -- just call `drop_table` -- but the `down` part, generating the table again, might not always be so simple, especially if the schema of the table in question has been changed by migrations after its initial creation. Maybe someone should suggest to the developers of Rails that adding such an option would be a good idea. – Teemu Leisti Sep 12 '12 at 12:14
  • 4
    @TeemuLeisti How about just copy and paste the current table definition from schema.rb? I do it this way all the time... – jasoares Aug 31 '13 at 17:22
  • 1
    @João Soares: OK, I guess that works. However, it would be nice if the process could be automated, so that you could just give a `rake` migration-creation command, with the name of a table as a parameter, that would produce the needed `up` and `down` functions. – Teemu Leisti Sep 02 '13 at 09:08

22 Answers22

677

You won't always be able to simply generate the migration to already have the code you want. You can create an empty migration and then populate it with the code you need.

You can find information about how to accomplish different tasks in a migration here:

http://api.rubyonrails.org/classes/ActiveRecord/Migration.html

More specifically, you can see how to drop a table using the following approach:

drop_table :table_name
Joe Kennedy
  • 8,605
  • 7
  • 38
  • 51
Pete
  • 17,037
  • 4
  • 30
  • 30
  • 3
    This worked for me too. But on full migrations (installing from scratch) the table will now be first created and later on dropped again. Is it safe to remove the create and drop migrations down the road? – berkes Jan 17 '11 at 20:04
  • 1
    If no other migration uses that table (adding/removing columns, adjusting column attributes, etc.) then it might not harm anything to remove the create/drop migrations. However I'm not sure removing them will buy you any significant improvements. Is there some particular reason you're looking to remove them? – Pete Jan 19 '11 at 00:52
  • 3
    Any view here on whether it's better to drop tables or revert to a previous database schema? – william tell May 11 '12 at 16:23
  • 4
    If you're done with the table and do not plan to use it anymore, I'd say just drop it. Better to get rid of it if its not being used. – Pete May 11 '12 at 21:57
  • 8
    [answer](https://stackoverflow.com/questions/4020131/rails-db-migration-how-to-drop-a-table/31657066#31657066) by @BederAcostaBorges is more self-explanatory and accurate – onerinas May 03 '16 at 06:28
  • 3
    How to also remove all foreign keys? There are columns in other tables pointing to the table being dropped. – Martin Konicek May 08 '18 at 16:14
  • If you also want the migration to be reversible then add a block to the drop_table method that looks like what you would give to a create_table method, that way if you did a rollback the table structure would be created again http://joshfrankel.me/blog/ensure-dropping-a-database-table-is-reversible/ – Toby 1 Kenobi Aug 17 '18 at 12:05
  • @Martin Konicek, I highly recommend removing foreign keys from associated models *before* running drop_table, eg. `remove_index :table_name, :associated_id` then `remove_column :table_name, :associated_id` then `drop_table :associated_table_name`. – MSC Feb 01 '19 at 02:29
367

First generate an empty migration with any name you'd like. It's important to do it this way since it creates the appropriate date.

rails generate migration DropProductsTable

This will generate a .rb file in /db/migrate/ like 20111015185025_drop_products_table.rb

Now edit that file to look like this:

class DropProductsTable < ActiveRecord::Migration
  def up
    drop_table :products
  end

  def down
    raise ActiveRecord::IrreversibleMigration
  end
end

The only thing I added was drop_table :products and raise ActiveRecord::IrreversibleMigration.

Then run rake db:migrate and it'll drop the table for you.

Brandon O'Rourke
  • 22,455
  • 14
  • 51
  • 58
  • 15
    A down migration should be used to recreate the table being dropped. – fflyer05 Jan 09 '14 at 01:34
  • 1
    This migration could never be rolled back, even in development. Would it be better to just leave the down migration blank? – mhriess Apr 04 '14 at 17:07
  • 1
    This is the better answer + fflyer's comment – Zack Shapiro Jun 15 '14 at 08:25
  • 2
    @mjnissim and fflyer05 are correct, in order to avoid any weird thing you should recreate the table in the down method. – Sebastialonso Jan 23 '15 at 16:43
  • 1
    To make the migration reversible, modify the code as follows. I prefer to use the change method, instead of having a separate up and down method, so the same code works both ways `def change; ` `drop_table :products do |t|; t.string :product_name, null: false; t.timestamps null: false; end; end;` – user3402754 Jan 23 '17 at 15:26
  • 9
    Dropping a table deletes all the data, if you recreate it in the `down` method you won't recover it so it's not actually a proper roll back. It's better to clearly indicate that the migration is irreversible than to give a false sense that it can be recovered from. – vivi Dec 28 '18 at 15:42
340

Write your migration manually. E.g. run rails g migration DropUsers.

As for the code of the migration I'm just gonna quote Maxwell Holder's post Rails Migration Checklist

BAD - running rake db:migrate and then rake db:rollback will fail

class DropUsers < ActiveRecord::Migration
  def change
    drop_table :users
  end
end

GOOD - reveals intent that migration should not be reversible

class DropUsers < ActiveRecord::Migration
  def up
    drop_table :users
  end

  def down
    fail ActiveRecord::IrreversibleMigration
  end
end

BETTER - is actually reversible

class DropUsers < ActiveRecord::Migration
  def change
    drop_table :users do |t|
      t.string :email, null: false
      t.timestamps null: false
    end
  end
end
Beder Acosta Borges
  • 4,600
  • 2
  • 24
  • 20
  • 2
    If you're cutting and pasting into the block from `schema.rb`, don't forget to also search `schema.rb` for foreign keys. Then add the foreign key definition to the `drop_table` block, e.g.: `t.foreign_key "other_table"` – Lencho Reyes Jul 02 '19 at 20:10
  • I used the 3rd option and it worked perfectly fine for me. Thank you. – Promise Preston Jan 20 '21 at 18:32
203

While the answers provided here work properly, I wanted something a bit more 'straightforward', I found it here: link First enter rails console:

$rails console

Then just type:

ActiveRecord::Migration.drop_table(:table_name)

And done, worked for me!

webaholik
  • 1,218
  • 15
  • 27
lllllll
  • 4,349
  • 5
  • 26
  • 41
  • The model is still there until you run `rails destroy model User` – gm2008 Jul 13 '14 at 12:29
  • 2
    Only run this if you want to get rid of the table for good. Rails will be unaware of this drop. Migration is broken after running this command. Can not CREATE, DROP...ETC. ERROR SQLite3::SQLException: no such table: accruals: DROP TABLE "sometable" – z atef Aug 23 '17 at 14:13
38

You need to to create a new migration file using following command

rails generate migration drop_table_xyz

and write drop_table code in newly generated migration file (db/migration/xxxxxxx_drop_table_xyz) like

drop_table :tablename

Or if you wanted to drop table without migration, simply open rails console by

$ rails c

and execute following command

ActiveRecord::Base.connection.execute("drop table table_name")

or you can use more simplified command

ActiveRecord::Migration.drop_table(:table_name)
Shahzad Tariq
  • 2,487
  • 1
  • 19
  • 31
21
  1. rails g migration drop_users
  2. edit the migration
    class DropUsers < ActiveRecord::Migration
      def change
        drop_table :users do |t|
          t.string :name
          t.timestamps
        end
      end
    end
  1. rake db:migrate
ssarabando
  • 3,159
  • 2
  • 36
  • 40
Aashish Saini
  • 221
  • 2
  • 6
14

I think, to be completely "official", you would need to create a new migration, and put drop_table in self.up. The self.down method should then contain all the code to recreate the table in full. Presumably that code could just be taken from schema.rb at the time you create the migration.

It seems a little odd, to put in code to create a table you know you aren't going to need anymore, but that would keep all the migration code complete and "official", right?

I just did this for a table I needed to drop, but honestly didn't test the "down" and not sure why I would.

Francis Potter
  • 1,599
  • 1
  • 16
  • 19
  • 1
    Strange but it looks like I'm going to have to do this too. – digitalWestie Jul 12 '11 at 15:20
  • 8
    Or you can just use: `raise ActiveRecord::IrreversibleMigration` in the self.down method, so you at LEAST give yourself an error / notice if you ever try to rollback. – Steph Rose Mar 14 '12 at 15:55
  • 2
    I would test the down just because otherwise I'm introducing untested code into my project. How can I reuse the original migration's up method? I've tried `CreateMyTable.up` and `ActiveRecord::Migrator.run(:up, ActiveRecord::Migrator.migrations_paths, X)` where X is the migration that originally created the table, but neither works--in both approaches, AR first checks whether the migration has already been applied, and silently skips it if it has. ` – Isaac Betesh Jun 05 '13 at 14:45
13

The simple and official way would be this:

  rails g migration drop_tablename

Now go to your db/migrate and look for your file which contains the drop_tablename as the filename and edit it to this.

    def change
      drop_table :table_name
    end

Then you need to run

    rake db:migrate 

on your console.

Mahesh Mesta
  • 663
  • 1
  • 10
  • 24
12

you can simply drop a table from rails console. first open the console

$ rails c

then paste this command in console

ActiveRecord::Migration.drop_table(:table_name)

replace table_name with the table you want to delete.

you can also drop table directly from the terminal. just enter in the root directory of your application and run this command

$ rails runner "Util::Table.clobber 'table_name'"
Farzpal Singh
  • 254
  • 2
  • 8
12

I wasn't able to make it work with migration script so I went ahead with this solution. Enter rails console using the terminal:

rails c

Type

ActiveRecord::Migration.drop_table(:tablename)

It works well for me. This will remove the previous table. Don't forget to run

rails db:migrate
Srikanth V
  • 171
  • 2
  • 5
10

You can roll back a migration the way it is in the guide:

http://guides.rubyonrails.org/active_record_migrations.html#reverting-previous-migrations

Generate a migration:

rails generate migration revert_create_tablename

Write the migration:

require_relative '20121212123456_create_tablename'

class RevertCreateTablename < ActiveRecord::Migration[5.0]
  def change
    revert CreateTablename    
  end
end

This way you can also rollback and can use to revert any migration

Matheus
  • 920
  • 12
  • 25
8

Alternative to raising exception or attempting to recreate a now empty table - while still enabling migration rollback, redo etc -

def change
  drop_table(:users, force: true) if ActiveRecord::Base.connection.tables.include?('users')
end
shivam
  • 14,497
  • 1
  • 47
  • 64
aqwan
  • 330
  • 3
  • 5
7

Open you rails console

ActiveRecord::Base.connection.execute("drop table table_name")
Mike H-R
  • 7,147
  • 5
  • 37
  • 58
manish nautiyal
  • 2,388
  • 3
  • 24
  • 34
5

ActiveRecord::Base.connection.drop_table :table_name

Dorian
  • 19,009
  • 8
  • 108
  • 111
nhegroj
  • 59
  • 1
  • 3
  • If you are working in a development environment this is a much easier solution than answers with more votes – Kai Durai Jan 07 '21 at 14:38
2

I needed to delete our migration scripts along with the tables themselves ...

class Util::Table < ActiveRecord::Migration

 def self.clobber(table_name)   
    # drop the table
    if ActiveRecord::Base.connection.table_exists? table_name
      puts "\n== " + table_name.upcase.cyan + " ! " 
           << Time.now.strftime("%H:%M:%S").yellow
      drop_table table_name 
    end

    # locate any existing migrations for a table and delete them
    base_folder = File.join(Rails.root.to_s, 'db', 'migrate')
    Dir[File.join(base_folder, '**', '*.rb')].each do |file|
      if file =~ /create_#{table_name}.rb/
        puts "== deleting migration: " + file.cyan + " ! "
             << Time.now.strftime("%H:%M:%S").yellow
        FileUtils.rm_rf(file)
        break
      end
    end
  end

  def self.clobber_all
    # delete every table in the db, along with every corresponding migration 
    ActiveRecord::Base.connection.tables.each {|t| clobber t}
  end

end

from terminal window run:

$ rails runner "Util::Table.clobber 'your_table_name'"

or

$ rails runner "Util::Table.clobber_all"
icedwater
  • 4,280
  • 3
  • 31
  • 47
Aaron Henderson
  • 1,681
  • 19
  • 19
2

if anybody is looking for how to do it in SQL.

type rails dbconsole from terminal

enter password

In console do

USE db_name;

DROP TABLE table_name;

exit

Please dont forget to remove the migration file and table structure from schema

Shan
  • 501
  • 5
  • 19
1

Run

rake db:migrate:down VERSION=<version>

Where <version> is the version number of your migration file you want to revert.

Example:-

rake db:migrate:down VERSION=3846656238
venkatvb
  • 673
  • 1
  • 9
  • 23
Rankit Ranjan
  • 39
  • 1
  • 3
1

the best way you can do is

rails g migration Drop_table_Users

then do the following

rake db:migrate
Anoob K Bava
  • 508
  • 4
  • 19
-1

Run this command:-

rails g migration drop_table_name

then:

rake db:migrate

or if you are using MySql database then:

  1. login with database
  2. show databases;
  3. show tables;
  4. drop table_name;
Dov Benyomin Sohacheski
  • 5,155
  • 7
  • 31
  • 54
-1

Drop Table/Migration

run:- $ rails generate migration DropTablename

exp:- $ rails generate migration DropProducts

-1

if you want to drop a specific table you can do

$ rails db:migrate:up VERSION=[Here you can insert timestamp of table]

otherwise if you want to drop all your database you can do

$rails db:drop
Nicollas
  • 192
  • 9
-3

If you want to delete the table from the schema perform below operation --

rails db:rollback
Suraj Rao
  • 28,186
  • 10
  • 88
  • 94
iamnair
  • 1
  • 1
  • This command will only undo the last migrate command. If that command is the creation of the table, it will drop the table. But unless you then delete the migration file that creates it, it will be recreated the at the next `db:migrate`. Keeping your migrations in order to replicate elsewhere is important, especially if work has been done in the meantime. Using `db:rollback` to change the final database layout is almost guaranteed to ruin many people's work. – Sean Hogge Sep 21 '20 at 14:57